/* $Header: pi_inlet.c,v 2.2 01/10/02 10:27:58 przybyls Exp $ */

/***********************************************************************/
/*                                                                     */
/*                  Copyright Hewlett-Packard Co. 1991                 */
/*                                                                     */
/***********************************************************************/

/***********************************************************************/
/* MODULE NAME:                                                        */
/* ============                                                        */
/*                                                                     */
/* Author:                                                             */
/*                                                                     */
/* MODULE PURPOSE:                                                     */
/*                                                                     */
/*                                                                     */
/*                                                                     */
/*                                                                     */
/***********************************************************************/


/*****************************/
/*   GLOBAL INCLUDE FILES    */
/*****************************/

#include <typedefs.h>
#include <p_wkfile.h>
#include <wkfile.h>
#include <i_op.h>
#include <p_status.h>
#include <pcb_defs.h>
#include <list_mgmt.h>
#include <ramps.h>         /* needed for status.h */
#include <zone_config.h>   /* needed for status.h */
#include <zone_status.h>   /* needed for status.h */
#include <status.h>     /* definition of Oven_Table */
#include <math.h>
#include <error.h>       /* needed for zone_ui.h */
#include <zone_ui.h>     /* to get time <--> millisec conversions */
#include <oven.h>        /* to get DetermineInletZoneConfig proto */
#include <exception.h>   /* to use SetException */
#include <err_handler.h> /* to use SetException */
#include <glp.h>
#include <clock_ui.h>
#include <keyboard.h>
#include <run_ui.h>

/*****************************/
/*   LOCAL INCLUDE FILES     */
/*****************************/

#include "proto.h"
#include "p_tcomp.h"

/*****************************/
/*   GLOBAL VARIABLES        */
/*****************************/

#define MAX(x,y) (((x)>(y))?(x):(y))
#define MIN(x,y) (((x)<(y))?(x):(y))


/*****************************/
/*   EXTERNAL VARIABLES      */
/*****************************/


/*****************************/
/*   LOCAL DEFINES           */
/*****************************/

#define OLD_MISER_MODE 0

#define SCALING_SCALE_FACTOR    0x100

/*****************************/
/*   STATIC VARIABLES        */
/*****************************/


/*****************************/
/*   IMPLEMENT SECTION       */
/*****************************/

/**begin_proto**/
#pragma SECTION PROG=rom3
/**end_proto**/
/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

U_INT32 CalcSplitRatioFromTotalFlow( pINLET_STATUS status, U_INT32 total_flow, U_INT16 pres, U_INT16 oven_temp )

/**end_proto**/
{
    U_INT16 p_iu;
    U_INT32 column_flow;
    U_INT32 purge_flow;
    U_INT32 split_flow;
    U_INT32 split_ratio;

          p_iu = pres;

          purge_flow = CalcSeptumPurgeFlow ( status, p_iu );


          column_flow =  CalcTotalColumnFlowNTP ( status->Position,
                             p_iu,
                             oven_temp,
                             status->IU_Scaling );

          if ( total_flow > ( purge_flow + column_flow ) )
          {
               split_flow = total_flow - purge_flow - column_flow;
          }
          else
          {
               split_flow = 0;
          }

          if ( column_flow == 0 )
          {
                split_ratio = 100 * SPLIT_RATIO_INTERNAL_SCALE;
          }
          else
          {
                split_ratio = QuadWordMultiplyDivide( split_flow, SPLIT_RATIO_INTERNAL_SCALE, column_flow );

                if (( split_flow == 0 ) || ( split_ratio < MIN_SPLIT_RATIO_IU ))
                {
                      split_ratio = MIN_SPLIT_RATIO_IU;
                }

                if ( split_ratio > MAX_SPLIT_RATIO_IU )
                {
                      split_ratio = MAX_SPLIT_RATIO_IU;
                }
          }

     return split_ratio;
}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

U_INT32 CalcPurgeFlowFromTotalFlow( pINLET_STATUS status, U_INT32 total_flow )

/**end_proto**/
{
    U_INT16 p_iu;
    U_INT32 column_flow;
    U_INT32 septum_purge_flow;
    U_INT32 purge_flow;

          p_iu =  CalcColumnInitP(
                  ( Inst_Config.Pneu.Column_1.Source == status->Position ?
                                              &Inst_Status.Pneu.Column_1 :
                                              &Inst_Status.Pneu.Column_2  ));

          septum_purge_flow = CalcSeptumPurgeFlow ( status, p_iu );


          column_flow =  CalcTotalColumnFlowNTP ( status->Position,
                             p_iu,
                             GetOvenInitTemp(),
                             status->IU_Scaling );


          if ( total_flow > ( septum_purge_flow + column_flow ) )
          {
               purge_flow = total_flow - septum_purge_flow - column_flow;
          }
          else
          {
               purge_flow = 0;
          }

     return purge_flow;
}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

void NewlyDefinedColOnSsInlet ( pINLET_STATUS status )

/**end_proto**/
{
     if ( status->Has_Column == FALSE ) return;  /* still one undefined col on inlet */

     if (( status->Wkfile->Injection_Mode == SPLIT ) ||
         ( status->Wkfile->Injection_Mode == SPLIT_PULSED ))
     {
         /* we are now using split ratio, so calc it from */
         /* total flow and the now available column flow  */

         status->Wkfile->Split_Ratio = CalcSplitRatioFromTotalFlow ( status,
                                                                     status->Wkfile->Total_Inlet_Flow,
                                                                     CalcColumnInitP(
                  ( Inst_Config.Pneu.Column_1.Source == status->Position ? &Inst_Status.Pneu.Column_1 :
                                                                           &Inst_Status.Pneu.Column_2  )),

                                                                     GetOvenInitTemp() );
     }
     else
     {
         /* we are now using purge_flow, so calc it from */
         /* total flow and the now available column flow */
         status->Wkfile->Purge_Flow = CalcPurgeFlowFromTotalFlow( status, status->Wkfile->Total_Inlet_Flow );
     }
}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/***********************************************************************/

/**begin_proto**/

U_INT32 FindInletFlows ( pINLET_STATUS status, U_INT16 pres )

/**end_proto**/
{
    U_INT32 septum;
    U_INT32 column;
    U_INT32 split;
    U_INT32 total;
    U_INT32 max;
    BIT8    to_big;

    septum = CalcSeptumPurgeFlow ( status, pres );

    column  = CalcTotalColumnFlowNTP (   status->Position,
                                         pres,
                                         GetOvenInitTemp(),
                                         status->IU_Scaling );


    max = GetInletMaxFlowIu ( status, status->IU_Scaling );

    if (( status->Wkfile->Injection_Mode == SPLIT ) ||
        ( status->Wkfile->Injection_Mode == SPLIT_PULSED ))
    {
        split = BoundsCheckedQWMD      ( column,
                                         status->Wkfile->Split_Ratio,
                                         SPLIT_RATIO_INTERNAL_SCALE,
                                         max,
                                         &to_big );
        total = column + septum + split;

        if ( to_big ) total = max;
    }
    else
    {
        total = column + septum;
    }

    return total;
}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/* CALLS:                                                              */
/*                                                                     */
/* LIMITATIONS:                                                        */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/
INT32 GetRealInletPresActual( pINLET_STATUS status )
/**end_proto**/
{

    U_INT16 Pntp;

    Pntp = status->Filtered_Current_Pressure;

    return ConvertPresIuToDisplay ( Pntp, status->Dcm2_Per_IU );
}

/**begin_proto**/
INT32 GetInletPresActual( pINLET_STATUS status )
/**end_proto**/
{

    U_INT16 Pntp;

    /* we have rounding problems, the setpt could truly be
        3.252 and the actual 3.247 and be within all noise
       and filter constraints.  So... rather than doing anything
       fancy, if we are ready, just return the setpt.  And..
       no more  rounding problems!  */

    if  (( status->Ready.Pres.State == IN_CONTROL_ ) || ( status->Ready.Pres.State == NOT_READY_DELAY ))
    {
        Pntp = status->Delayed_NTP_Inlet_Pres_Setpt;
    }
    else
    {
        Pntp = status->NTP_Adjusted_Current_Pressure;
    }

    return ConvertPresIuToDisplay ( Pntp, status->Dcm2_Per_IU );
}

/**begin_proto**/
INT32 DcGetInletPresActual( pINLET_STATUS status )
/**end_proto**/
{
    U_INT16 Pntp;

    Pntp = status->NTP_Adjusted_Current_Pressure;

    return ConvertPresIuToDcu ( Pntp, status->Dcm2_Per_IU );
}

/**begin_proto**/
INT32 GetInletPresSetpt( pINLET_STATUS status )
/**end_proto**/
{
    U_INT16 Pntp;

#if 0
    Pntp = status->Filtered_Pressure_Setpt;
    Pntp = status->Inlet_Pressure_Setpt;
#else
    Pntp = status->Delayed_NTP_Inlet_Pres_Setpt;
#endif

    return ConvertPresIuToDisplay ( Pntp, status->Dcm2_Per_IU );

}

/**begin_proto**/
INT32 DcGetInletPresSetpt( pINLET_STATUS status )
/**end_proto**/
{
    U_INT16 Pntp;

    if (( status->Config->Type == PP      ) && ( !status->Has_Column )) return -1;
    if (( status->Config->Type == ACI     ) && ( !status->Has_Column )) return -1;
    if (( status->Config->Type == SIMDIST ) && ( !status->Has_Column )) return -1;

    Pntp = status->Delayed_NTP_Inlet_Pres_Setpt;

    return ConvertPresIuToDcu ( Pntp, status->Dcm2_Per_IU );
}


/**begin_proto**/
INT32 DcGetInletWkfilePresSetpt( pINLET_STATUS status )
/**end_proto**/
{
    U_INT16 Pntp;

    if (( status->Config->Type == SIMDIST  ) && ( !status->Has_Column )) return -1;
    if (( status->Config->Type == PP       ) && ( !status->Has_Column )) return -1;
    if (( status->Config->Type == ACI      ) && ( !status->Has_Column )) return -1;

    Pntp = status->Wkfile->Inlet_Pressure;

    return ConvertPresIuToDcu ( Pntp, status->Dcm2_Per_IU );
}

/**begin_proto**/
UI_ERR  SetInletPresSetpt( INT32 setpt, pINLET_STATUS status )
/**end_proto**/
{
    U_INT32  p_iu;
    UI_ERR   validate;

    p_iu = ConvertPresDisplayToIu(setpt, status->Dcm2_Per_IU );

    validate = ValidateInletPresSetpt( setpt, status );

    if ( validate == OK )
    {
         LockResource( &Inst_Status.Pneu.Resource_Lock );

         ChangeInletPresSetpt ( p_iu, setpt, status, GetCurrentOvenTemp() );

         if ( setpt > 0 )
         {
              ChangeInletState( ON, status );
         }

         ReleaseResource( &Inst_Status.Pneu.Resource_Lock );
    }

    return validate;
}

/**begin_proto**/
UI_ERR  DcSetInletPresSetpt( INT32 setpt, pINLET_STATUS status )
/**end_proto**/
{
    U_INT32  p_iu;
    INT32    p_display_units;
    UI_ERR   validate;

    p_iu = ConvertPresDcuToIu(setpt, status->Dcm2_Per_IU );

    /* next line is a consession to Chemstation; if VI Flow is active, CS really should send ",,", NOT ",P,"  !! */
    if ( (status->VI_Flow_Mode ) && status->Wkfile->Inlet_Pressure != p_iu )  return NOT_ALLOWED;

    p_display_units = ConvertPresIuToDisplay ( p_iu, status->Dcm2_Per_IU );
    validate = ValidateInletPresSetpt( p_display_units, status );

    if ( validate == OK )
    {
#if 1
         ChangeInletPresSetpt ( p_iu, p_display_units, status, GetOvenInitTemp() );
#else
         status->Wkfile->Inlet_Pressure = p_iu;
         LogSetptChange( status->Position == FRNT_INLET ? F_INLET_PRES : B_INLET_PRES, setpt, (INT32)GetPresUnits() );
#endif
    }

    return validate;
}


/**begin_proto**/
UI_ERR  DcSetInletPresSetptImmediate( INT32 setpt, pINLET_STATUS status )
/**end_proto**/
{
    U_INT32  p_iu;
    INT32    p_display_units;
    UI_ERR   validate;

    p_iu = ConvertPresDcuToIu(setpt, status->Dcm2_Per_IU );

    p_display_units = ConvertPresIuToDisplay ( p_iu, status->Dcm2_Per_IU );

    validate = ValidateInletPresSetpt( p_display_units, status );

    #if 0 /* next line added by R. Wikfors on 3.1->3.2 transition. No A104...A111 had it & it kills mfg. process. */
          /* RW does not recall reason for chg as of 8/1/96 , so for now it will be deleted . SOK 8/1/96          */
    if ( ! status->Controlled_By_Column ) validate = NOT_ALLOWED;
    #endif

    if ( validate == OK )
    {
         ChangeInletPresStatus( p_iu, p_display_units, status, GetCurrentOvenTemp() );
    }

    return validate;
}

/**begin_proto**/
UI_ERR ValidateInletPresSetpt ( INT32 pres, pINLET_STATUS status )
/**end_proto**/
{
     switch ( status->Config->Type )
     {

          case VOLATILES:
          case SS:
          case PTV:
          case CIS3:
          case CIS4:
          case COC:            break;

          case ACI:
          case SIMDIST:
          case PP:  if ( status->Has_Column ) break;
                    /* intentional fall through */

          case MANUAL_PP:
          case MANUAL_COC:
          case MANUAL_ACI:
          case MANUAL_SS:
          case UNKNOWN_INLET:  return INVALID_PARAM;

          case NO_INLET:       return NOT_INSTALLED;
     }

      if ( pres < 0 ) return  PARAM_TOO_SMALL;
      if ( pres > GetInletMaxPres( status ) ) return PARAM_TOO_LARGE;

     return OK;
}

/**begin_proto**/
void ChangeInletPresSetpt ( U_INT16 p_iu, INT32 setpt,  pINLET_STATUS status, U_INT16 oven_temp )
/**end_proto**/
{

    if ( status->Controlled_By_Column )
    {
        UpdateColumnsDamnIt ( p_iu, oven_temp, status->Position, status->Dcm2_Per_IU );
    }
    else
    {
        UpdateInletPresSetpt( p_iu, status, status->Dcm2_Per_IU );

        status->Delayed_NTP_Inlet_Pres_Setpt = p_iu; /* let the filter go right to this value */
    }

    if ( CheckForPressurePulse( status ) == FALSE ) SlamInletSetpt( status );

    LogSetptChange( status->Position == FRNT_INLET ? F_INLET_PRES : B_INLET_PRES, setpt, (INT32)GetPresUnits() );

    status->Ready.Setpt_Change = TRUE;
}


/**begin_proto**/
void ChangeInletPresStatus( U_INT16 p_iu, INT32 setpt,  pINLET_STATUS status, U_INT16 oven_temp )
/**end_proto**/
{

    if ( RunActiveOrPostTime() == FALSE )
    {
         UpdateInletPresStatus( p_iu, status, status->Dcm2_Per_IU );

         status->Delayed_NTP_Inlet_Pres_Setpt = p_iu; /* let the filter go right to this value */
    }

    UpdateColumns ( p_iu, oven_temp, status->Position, status->Dcm2_Per_IU );

    if ( CheckForPressurePulse( status ) == FALSE ) SlamInletSetpt( status );

    LogSetptChange( status->Position == FRNT_INLET ? F_INLET_PRES : B_INLET_PRES, setpt, (INT32)GetPresUnits() );

    status->Ready.Setpt_Change = TRUE;
}



/**begin_proto**/
void UpdateInletPresStatus( U_INT16 p_iu,  pINLET_STATUS status, U_INT16 dcm2_per_iu )
/**end_proto**/
{
    p_iu = (U_INT32)p_iu * dcm2_per_iu / status->Dcm2_Per_IU;


    status->Wkfile->Inlet_Pressure =  p_iu;

    if ( status->Has_Column )  /* calc value for no columns defined */
    {
        status->Wkfile->Total_Inlet_Flow =  FindInletFlows ( status, p_iu );

        /* if we are defined, flows are calculated based on pressure.  Slam the value */
        status->Slam_Flow_Setpt = TRUE;
    }


    if ( ! status->Controlled_By_Column )    /* no column defined, we are truly using Wkfile->Inlet_Pressure  */
    {
        if ( CheckForPressurePulse( status ) == FALSE ) SlamInletPresSetpt( p_iu, status );
        status->Ready.Setpt_Change = TRUE;
    }
}



/**begin_proto**/
void UpdateInletPresSetpt ( U_INT16 p_iu,  pINLET_STATUS status, U_INT16 dcm2_per_iu )
/**end_proto**/
{
    p_iu = (U_INT32)p_iu * dcm2_per_iu / status->Dcm2_Per_IU;

    status->Wkfile->Inlet_Pressure =  p_iu;

    if ( status->Has_Column )  /* calc value for no columns defined */
    {
        status->Wkfile->Total_Inlet_Flow =  FindInletFlows ( status, p_iu );
    }
}


/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/* CALLS:                                                              */
/*                                                                     */
/* LIMITATIONS:                                                        */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

INT32 GetRealInletFlowActual( pINLET_STATUS status )

/**end_proto**/
{

    return ConvertFlowIuToDisplay ( status->Real_Filtered_Flow, status->IU_Scaling );

}

/**begin_proto**/

INT32 GetInletFlowActual( pINLET_STATUS status )

/**end_proto**/
{



    U_INT32 flow;

    /* we have rounding problems, the setpt could truly be
        3.252 and the actual 3.247 and be within all noise
       and filter constraints.  So... rather than doing anything
       fancy, if we are ready, just return the setpt.  And..
       no more  rounding problems!  */

    if  (( status->Ready.Flow.State == IN_CONTROL_ ) || ( status->Ready.Flow.State == NOT_READY_DELAY ))
    {
        flow = status->Delayed_NTP_Inlet_Flow_Setpt;
    }
    else
    {
        flow = status->NTP_Adjusted_Current_Flow;
    }


    return ConvertFlowIuToDisplay ( flow, status->IU_Scaling );

}

/**begin_proto**/

INT32 DcGetInletFlowActual( pINLET_STATUS status )

/**end_proto**/
{

    return ConvertFlowIuToDcu ( status->NTP_Adjusted_Current_Flow, status->IU_Scaling );

}

/**begin_proto**/

INT32 GetInletFlowSetpt( pINLET_STATUS status )

/**end_proto**/
{
    return ConvertFlowIuToDisplay ( status->Delayed_NTP_Inlet_Flow_Setpt, status->IU_Scaling );
}

/**begin_proto**/

INT32 DcGetInletFlowSetpt( pINLET_STATUS status )

/**end_proto**/
{
    if (( status->Config->Type == PP      ) && ( status->Has_Column )) return -1;
    if (( status->Config->Type == ACI     ) && ( status->Has_Column )) return -1;
    if (( status->Config->Type == SIMDIST ) && ( status->Has_Column )) return -1;
    if  ( status->Config->Type == COC )                                return -1;

    return ConvertFlowIuToDcu ( status->Delayed_NTP_Inlet_Flow_Setpt, status->IU_Scaling );
}


/**begin_proto**/

INT32 DcGetInletWkfileFlowSetpt( pINLET_STATUS status )

/**end_proto**/
{
    if (( status->Config->Type == SIMDIST ) && ( status->Has_Column )) return -1;
    if (( status->Config->Type == PP      ) && ( status->Has_Column )) return -1;
    if (( status->Config->Type == ACI     ) && ( status->Has_Column )) return -1;
    if  ( status->Config->Type == COC     )                            return -1;

    return ConvertFlowIuToDcu ( status->Wkfile->Total_Inlet_Flow, status->IU_Scaling );
}



/**begin_proto**/

UI_ERR SetInletFlowSetpt( INT32 flow, pINLET_STATUS status )

/**end_proto**/
{
    UI_ERR validate;
    U_INT32 v_flow;

    v_flow = ConvertFlowDisplayToIu(flow, status->IU_Scaling );

    validate = ValidateInletFlowSetpt( flow, status );

    if ( validate == OK )
    {
        LockResource( &Inst_Status.Pneu.Resource_Lock );

        ChangeInletFlowSetpt ( v_flow, flow, status );

        if ( flow > 0 )
        {
             ChangeInletState( ON, status );
        }

        ReleaseResource( &Inst_Status.Pneu.Resource_Lock );
    }

    return validate;
}


/**begin_proto**/

UI_ERR DcSetInletFlowSetpt( INT32 flow, pINLET_STATUS status )

/**end_proto**/
{
    UI_ERR validate;
    U_INT32 v_flow;
    INT32   flow_display;

    v_flow = ConvertFlowDcuToIu(flow, status->IU_Scaling );
    flow_display = ConvertFlowIuToDisplay(v_flow, status->IU_Scaling );

    validate = ValidateInletFlowSetpt( flow_display, status );

    if ( validate == OK )
    {
        ChangeInletFlowSetpt ( v_flow, flow_display, status );
    }
    return validate;
}


/**begin_proto**/

UI_ERR DcSetInletFlowSetptImmediate( INT32 flow, pINLET_STATUS status )

/**end_proto**/
{
    UI_ERR validate;
    U_INT32 v_flow;
    INT32   flow_display;

    v_flow = ConvertFlowDcuToIu(flow, status->IU_Scaling );
    flow_display = ConvertFlowIuToDisplay(v_flow, status->IU_Scaling );

    validate = ValidateInletFlowSetpt( flow_display, status );

    if ( validate == OK )
    {
        ChangeInletFlowSetpt ( v_flow, flow_display, status );
    }
    return validate;
}

/**begin_proto**/

UI_ERR ValidateInletFlowSetpt ( INT32 flow, pINLET_STATUS status )

/**end_proto**/
{
     U_INT32 purge_flow;
     U_INT32 split_flow;
     U_INT32 column_flow;
     BIT8    ovf;

     ovf = FALSE;

     switch ( status->Config->Type )
     {

          case VOLATILES:
          case CIS3:
          case CIS4:
          case SS:
          case PTV:            break;

          case ACI:
          case SIMDIST:
          case PP:   if ( ! status->Has_Column ) break;
                      /* intentional fall through */

          case COC:
          case MANUAL_SS:
          case MANUAL_PP:
          case MANUAL_ACI:
          case MANUAL_COC:
          case UNKNOWN_INLET:  return INVALID_PARAM;

          case NO_INLET:       return NOT_INSTALLED;

     }

     if ( flow < 0 ) return PARAM_TOO_SMALL;

     if (( status->Config->Type == SS ) && ( status->Has_Column ) &&
         (( status->Wkfile->Injection_Mode == SPLIT ) || ( status->Wkfile->Injection_Mode == SPLIT_PULSED )))
     {

         purge_flow = CalcSeptumPurgeFlow ( status, status->Inlet_Pressure_Setpt );

         column_flow =  CalcTotalColumnFlowNTP ( status->Position,
                            status->Inlet_Pressure_Setpt,
                            GetCurrentOvenTemp(),
                            status->IU_Scaling );

         if ( column_flow == 0 ) return OK;  /* will just set default split ratio */

         split_flow = QuadWordMultiplyDivide ( column_flow, MIN_SPLIT_RATIO_IU, SPLIT_RATIO_INTERNAL_SCALE );

         if ( flow < ConvertFlowIuToDisplay( column_flow + purge_flow + split_flow,
                                             status->IU_Scaling ) ) return PARAM_TOO_SMALL;

         split_flow = BoundsCheckedQWMD ( column_flow,
                                          GetMaxSplitRatioIu(status),
                                          SPLIT_RATIO_INTERNAL_SCALE,
                                          GetInletMaxFlowIu( status, status->IU_Scaling ),
                                          &ovf );

         if ( flow > ConvertFlowIuToDisplay( column_flow + purge_flow + split_flow, status->IU_Scaling ) )
             return PARAM_TOO_LARGE;
     }
     else if (( status->Config->Type == PP ) || ( status->Config->Type == ACI ) || ( status->Config->Type == SIMDIST ))
     {
         if (flow > GetInletMaxFlow ( status ) )     return PARAM_TOO_LARGE;
         if (flow < GetMinTotalInletFlow( status ) ) return PARAM_TOO_SMALL;
     }
     else
     {
         if (flow > GetInletMaxFlow ( status ) )     return PARAM_TOO_LARGE;
     }


     return OK;

}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

U_INT16 FindInletPresFromFlow ( pINLET_STATUS status, U_INT32 v_flow, U_INT16 oven_temp )

/**end_proto**/
{
   U_INT16 p_iu;
   U_INT16 increment;
   U_INT32 flow;


      /* iteratively search for a solution */
      p_iu = 0x8000;

      for ( increment = p_iu/2 ; increment > 0 ; increment /= 2 )
      {
           flow = 0;

           if ( Inst_Config.Pneu.Column_1.Source == status->Position )
           {
                flow += CalcVFlow( &Inst_Status.Pneu.Column_1, oven_temp, p_iu,
                               GetNtpOutletPressure(  &Inst_Status.Pneu.Column_1 ) );
           }
           if ( Inst_Config.Pneu.Column_2.Source == status->Position )
           {
                flow += CalcVFlow( &Inst_Status.Pneu.Column_2, oven_temp, p_iu,
                               GetNtpOutletPressure(  &Inst_Status.Pneu.Column_2 ) );
           }

           if (( status->Wkfile->Injection_Mode == SPLIT ) || ( status->Wkfile->Injection_Mode == SPLIT_PULSED ))
           {
                flow = QuadWordMultiplyDivide( flow, status->Wkfile->Split_Ratio, SPLIT_RATIO_INTERNAL_SCALE );
           }

           flow = CalcSeptumPurgeFlow ( status, p_iu );

           if ( flow > v_flow )
           {
                p_iu -= increment;
           }
           else
           {
                p_iu += increment;
           }
      }

      return p_iu;
}

/**begin_proto**/

void ChangeInletFlowSetpt( U_INT32 v_flow, INT32 flow, pINLET_STATUS status )

/**end_proto**/
{
    U_INT16 p_iu;
    U_INT32 purge_flow;
    U_INT16 oven_temp;
#if 0
    U_INT32 f1, f2, p1, p2, po;
#endif
    BIT8    ignored;

    ignored = FALSE;

    oven_temp = GetCurrentOvenTemp();

    if ( GenSS(status) && (( status->Wkfile->Injection_Mode == SPLIT        ) ||
                           ( status->Wkfile->Injection_Mode == SPLIT_PULSED )    ))
    {
          status->Wkfile->Split_Ratio = CalcSplitRatioFromTotalFlow ( status,
                                                                      v_flow,
                                                                      status->Inlet_Pressure_Setpt,
                                                                      oven_temp );
    }
    else if (  (( status->Config->Type == PP ) || ( status->Config->Type == SIMDIST ) || ( status->Config->Type == ACI ))
               && ( status->Has_Column == FALSE )  )  /* flow controlled */
    {
         /* purge flow at current pressure */
        purge_flow = CalcSeptumPurgeFlow ( status, MAX(status->Filtered_Current_Pressure,0x0001) );

#if 0
        if ( (status->NTP_Adjusted_Current_Flow - purge_flow) > 0 )
        {
            f1 = v_flow;
            f2 = (status->NTP_Adjusted_Current_Flow - purge_flow);
            p2 = MAX(status->Filtered_Current_Pressure, 0x0001);
            po = GetAmbientPressure( status->Dcm2_Per_IU );

            p1 = SqrtLU( ((f1/f2)*(p2*p2)) + ((1-f1/f2)*(po*po)) );

            p2 = GetInletMaxPresIu(status, status->Dcm2_Per_IU);

            if ( p1 > p2 ) p1 = p2;     /* bounds check */

            purge_flow = CalcSeptumPurgeFlow ( status, p1 );
        }

#else

         /* purge flow at estimate of new pressure */
        purge_flow = CalcSeptumPurgeFlow ( status,
                                           BoundsCheckedQWMD( SqrtLU(v_flow),
                                                              MAX(status->Filtered_Current_Pressure, 0x0001),
                                                              SqrtLU( (status->NTP_Adjusted_Current_Flow > purge_flow) ?
                                                                       status->NTP_Adjusted_Current_Flow - purge_flow  :
                                                                       0x00000001 ),
                                                              GetInletMaxPresIu(status, status->Dcm2_Per_IU),
                                                              &ignored ));
#endif

        if ( Inst_Config.Pneu.Column_1.Source == status->Position )
        {
             if ( Inst_Config.Pneu.Column_2.Source == status->Position )
             {                                                                /* both columns on same inlet */
                  UpdateColumnFlowSetpt( (v_flow < purge_flow) ? 0 : (v_flow - purge_flow)/2,
                                         &Inst_Status.Pneu.Column_1,
                                         status->IU_Scaling );
                  UpdateColumnFlowSetpt( (v_flow < purge_flow) ? 0 : (v_flow - purge_flow)/2,
                                         &Inst_Status.Pneu.Column_2,
                                         status->IU_Scaling );
             }
             else
             {                                                               /* only column 1 */
                  UpdateColumnFlowSetpt( (v_flow < purge_flow) ? 0 : v_flow - purge_flow,
                                         &Inst_Status.Pneu.Column_1,
                                         status->IU_Scaling );
             }
        }
        else if ( Inst_Config.Pneu.Column_2.Source == status->Position )
        {                                                                    /* only column 2 */
             UpdateColumnFlowSetpt( (v_flow < purge_flow) ? 0 : v_flow - purge_flow,
                                    &Inst_Status.Pneu.Column_2,
                                    status->IU_Scaling );
        }
    }
    else if (status->Has_Column == TRUE )   /* splitless and pressure controlled */
    {

          /* this case should be prohibitied by the keyboard */


        p_iu = FindInletPresFromFlow ( status, v_flow, oven_temp );

        if ( Inst_Config.Pneu.Column_1.Source == status->Position )
        {
             UpdateColumnSetpts( p_iu, oven_temp, &Inst_Status.Pneu.Column_1, status->Dcm2_Per_IU );
        }
        if ( Inst_Config.Pneu.Column_2.Source == status->Position )
        {
             UpdateColumnSetpts( p_iu, oven_temp, &Inst_Status.Pneu.Column_2, status->Dcm2_Per_IU );
        }

    }

   UpdateInletFlowSetpt( status, v_flow );

   LogSetptChange( status->Position == FRNT_INLET ? F_INLET_FLOW : B_INLET_FLOW, flow, 0 );

}


/**begin_proto**/

void UpdateInletFlowSetpt( pINLET_STATUS status, U_INT32 v_flow )

/**end_proto**/
{

   status->Wkfile->Total_Inlet_Flow = v_flow;

   status->Slam_Flow_Setpt = TRUE;

    status->Ready.Setpt_Change = TRUE;
}

/**begin_proto**/

void ModifyInletFlowSetpt( pINLET_STATUS status )

/**end_proto**/
{
    U_INT32 v_flow;

    /* W A R N I N G! only call for flow controlled PP  and ACI inlets!,  */
    /*                other calls will have no effect.                    */

    /* provide a clue that column flow setpts have changed. so that flow */
    /* controlled purged packed inlets can calculate new setpoints for   */
    /* total inlet flow.                                                 */

    if ((status->Has_Column != TRUE )
       && (( status->Config->Type == SIMDIST ) || ( status->Config->Type == PP ) || ( status->Config->Type == ACI )))
    {
         /* flow controlled, if no columns defined */
        v_flow  = CalcSeptumPurgeFlow ( status, status->Filtered_Current_Pressure );
        v_flow += GetTotalColumnF( status->Position, status->IU_Scaling, GetCurrentOvenTemp() );

        UpdateInletFlowSetpt( status, v_flow );
    }

    status->Ready.Setpt_Change = TRUE;
}


/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/* CALLS:                                                              */
/*                                                                     */
/* LIMITATIONS:                                                        */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

INJ_MODE GetInletInjectMode ( pINLET_STATUS status )

/**end_proto**/
{
     return status->Wkfile->Injection_Mode;
}

/**begin_proto**/

UI_ERR SetInletInjectMode( INJ_MODE state, pINLET_STATUS status )

/**end_proto**/
{
    UI_ERR validate;

    if ( GetInletInjectMode ( status ) == state ) return OK ;

    validate = ValidateInletInjectMode( state, status );

    if ( validate == OK )
    {
         LockResource( &Inst_Status.Pneu.Resource_Lock );

         ChgInletInjectMode( state, status ,0 );

         ReleaseResource( &Inst_Status.Pneu.Resource_Lock );
    }

    return validate;
}


/**begin_proto**/

UI_ERR DcSetInletInjectMode( INJ_MODE state, pINLET_STATUS status )

/**end_proto**/
{
    UI_ERR validate;

    if ( GetInletInjectMode ( status ) == state ) return OK ;

    validate = ValidateInletInjectMode( state, status );

    if ( validate == OK )
    {
         ChgInletInjectMode( state, status ,1 );
    }

    return validate;
}


/**begin_proto**/

UI_ERR ValidateInletInjectMode ( INJ_MODE state, pINLET_STATUS status )

/**end_proto**/
{

     switch ( state )
     {
          case      SPLIT:
          case      SPLITLESS:
          case      SPLITLESS_PULSED:
          case      SPLIT_PULSED:
          case      SOLVENT_VENT:
          case      DIRECT:     break ;

          default:  return INVALID_PARAM;
     }

     switch ( status->Config->Type )
     {

          case CIS4:
          case CIS3:      if ( state != DIRECT ) return OK;
                          break;

          case SS:
          case PTV:       switch (state)
                          {
                            case SOLVENT_VENT:
                            case DIRECT:           return  INVALID_PARAM;

                            default:               return OK;
                          }


          case VOLATILES: switch (state)
                          {
                            default:
                            case SOLVENT_VENT:
                            case SPLIT_PULSED:
                            case SPLITLESS_PULSED:  return INVALID_PARAM;

                            case DIRECT: return (GetVISplitPort(status)==CAPPED ? OK : INVALID_PARAM);

                            case SPLITLESS:
                            case SPLIT : return (GetVISplitPort(status)==PLUMBED ? OK : INVALID_PARAM);
                          }

          case MANUAL_SS: if (( state == SPLIT ) || ( state == SPLITLESS )) return OK;
                          break;

          case PP:
          case ACI:
          case SIMDIST:
          case COC:
          case MANUAL_PP:
          case MANUAL_ACI:
          case MANUAL_COC:   return INVALID_PARAM;

          case UNKNOWN_INLET:
          case NO_INLET:     return NOT_INSTALLED;

     }

     return INVALID_PARAM;

}


/**begin_proto**/

void ChgInletInjectMode( INJ_MODE state, pINLET_STATUS status, BIT8 DCflg )

/**end_proto**/
{
   if  ( GetInletType(status) == VOLATILES )
   {
      if (status->Wkfile->Injection_Mode == SPLIT)
      {  /* here b/c SPLIT -> SPLITLESS||DIRECT */
         status->Wkfile->VI_Inj_Time = status->Wkfile->VI_Inj_Time_Save ;

        /* must check for SAMPLING_END vs PNEU_INIT_TIME conflict here; if conflict then SAMPLING_END => INIT_TIME !! */

        if ( DCflg == 0  )
        {
           if ( (state==SPLITLESS ) && (GetInletMiserMode(status)==ON  ) ) FixMiserTime(status) ;
           FixVIPurgeTime(status) ;
        }

        if ( DoingMethodInstall()== 0 )
        {
           if ( Inst_Config.Pneu.Column_1.Source == status->Position )
           {
                VISamplingEndChk( &Inst_Status.Pneu.Column_1 );
           }
           if ( Inst_Config.Pneu.Column_2.Source == status->Position )
           {
                VISamplingEndChk( &Inst_Status.Pneu.Column_2 );
           }
        }

      };

      if (state == SPLIT )
      {  /* here b/c SPLITLESS||DIRECT -> SPLIT */
         status->Wkfile->VI_Inj_Time_Save  = status->Wkfile->VI_Inj_Time;
         status->Wkfile->VI_Inj_Time = 0;
      };

      #if 0
      if ( state == DIRECT )
      {  /* here b/c SPLITLESS||SPLIT -> DIRECT */
           status->Wkfile->VI_Auto_Cal_Save  = GetInletAutoCal(status);
           ChangeInletAutoCal( 0   , status );
      }

      if (status->Wkfile->Injection_Mode == DIRECT)
      {  /* here b/c DIRECT -> SPLITLESS||SPLIT */
           ChangeInletAutoCal( status->Wkfile->VI_Auto_Cal_Save   , status );
      }
      #endif

   }

   status->Wkfile->Injection_Mode = state;

   LogSetptChange( status->Position == FRNT_INLET ? F_INLET_INJECT_MODE : B_INLET_INJECT_MODE, 0, (INT32)state );

   status->Ready.Setpt_Change = TRUE;
}
/**begin_proto**/

void ChangeInletInjectMode( INJ_MODE state, pINLET_STATUS status )

/**end_proto**/
{
     ChgInletInjectMode( state, status ,0 );
}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/* CALLS:                                                              */
/*                                                                     */
/* LIMITATIONS:                                                        */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

BIT8 InletPurgeActive ( pINLET_STATUS status )

/**end_proto**/
{
     return status->Inlet_Purge;
}

/**begin_proto**/

BIT8 VIInjFlowActive ( pINLET_STATUS status )

/**end_proto**/
{
     return status->VI_Flow_Mode;
}

/**begin_proto**/

BIT8 InletPressurePulseActive ( pINLET_STATUS status )

/**end_proto**/
{
     return CheckForPressurePulse( status );
}

/**begin_proto**/

BIT8 InletMiserModeActive ( pINLET_STATUS status )

/**end_proto**/
{
     return CheckForMiserMode( status );
}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/* CALLS:                                                              */
/*                                                                     */
/* LIMITATIONS:                                                        */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

INT32 GetInletSplitFlow ( pINLET_STATUS status )

/**end_proto**/
{

       return ConvertFlowIuToDisplay ( status->Current_NTP_Split_Flow, status->IU_Scaling );

}

/**begin_proto**/

INT32 GetMaxSplitFlow( pINLET_STATUS status, U_INT32 column_flow )

/**end_proto**/
{

#if 0
       return ConvertFlowIuToDisplay ( column_flow * GetMaxSplitRatio( status ), status->IU_Scaling );
#else
       BIT8 ovf;

       ovf = FALSE;

       return ConvertFlowIuToDisplay (
                        BoundsCheckedQWMD(  column_flow,
                                            GetMaxSplitRatioIu( status ),
                                            SPLIT_RATIO_INTERNAL_SCALE,
                                            (9999 * status->IU_Scaling)
                                                - CalcSeptumPurgeFlow( status, status->Inlet_Pressure_Setpt )
                                                - column_flow,
                                            &ovf ),
                        status->IU_Scaling );

#endif

}


/**begin_proto**/

INT32 GetMinSplitFlow( pINLET_STATUS status, U_INT32 column_flow )

/**end_proto**/
{

       return ConvertFlowIuToDisplay (
               QuadWordMultiplyDivide ( column_flow, MIN_SPLIT_RATIO_IU, SPLIT_RATIO_INTERNAL_SCALE ),
               status->IU_Scaling );

}

/**begin_proto**/

INT32 GetMinTotalInletFlow( pINLET_STATUS status )

/**end_proto**/
{

    U_INT32 split_flow;
    U_INT32 purge_flow;
    U_INT32 column_flow;

    if (( status->Config->Type == SS ) && (( status->Wkfile->Injection_Mode == SPLIT ) ||
                                           ( status->Wkfile->Injection_Mode == SPLIT_PULSED )))
    {
          column_flow =  CalcTotalColumnFlowNTP ( status->Position,
                             status->Inlet_Pressure_Setpt,
                             GetCurrentOvenTemp(),
                             status->IU_Scaling );

          purge_flow = CalcSeptumPurgeFlow ( status, status->Inlet_Pressure_Setpt );

          split_flow = QuadWordMultiplyDivide ( column_flow, MIN_SPLIT_RATIO_IU, SPLIT_RATIO_INTERNAL_SCALE );

          return ConvertFlowIuToDisplay (column_flow+purge_flow+split_flow, status->IU_Scaling );
    }
    else
    {
        if (( status->Config->Type == PP ) || ( status->Config->Type == ACI ) || ( status->Config->Type == SIMDIST ))
        {
            purge_flow = CalcSeptumPurgeFlow ( status, 0 );
            return ConvertFlowIuToDisplay ( purge_flow, status->IU_Scaling );
        }
    }

    return 0;
}


/**begin_proto**/

INT32 DcGetInletSplitFlow ( pINLET_STATUS status )

/**end_proto**/
{
       U_INT32 column_flow;
       U_INT32 inlet_purge_flow;
       U_INT16 Pi;

       Pi = status->NTP_Adjusted_Current_Pressure;

       column_flow =  CalcTotalColumnFlowNTP ( status->Position, Pi, GetCurrentOvenTemp(), status->IU_Scaling );
       inlet_purge_flow = QuadWordMultiplyDivide ( column_flow,
                                                   status->Wkfile->Split_Ratio,
                                                   SPLIT_RATIO_INTERNAL_SCALE );

        return ConvertFlowIuToDcu ( inlet_purge_flow, status->IU_Scaling );

}

/**begin_proto**/

UI_ERR SetInletSplitFlow( INT32 flow, pINLET_STATUS status )

/**end_proto**/
{

    UI_ERR validate;
    U_INT32 split_flow;
    U_INT32 column_flow;  /* declared here and passed around to avoid duplicate calculations */


    validate = ValidateInletSplitFlow( flow, status, &column_flow );

    if ( validate == OK )
    {
        LockResource( &Inst_Status.Pneu.Resource_Lock );

        split_flow = ConvertFlowDisplayToIu(flow, status->IU_Scaling );

        ChangeInletSplitFlow ( split_flow, flow, status, column_flow );

        ReleaseResource( &Inst_Status.Pneu.Resource_Lock );
    }

    return validate;
}


/**begin_proto**/

UI_ERR DcSetInletSplitFlow( INT32 flow, pINLET_STATUS status )

/**end_proto**/
{


    UI_ERR  validate;
    U_INT32 split_flow;
    INT32   flow_display;
    U_INT32 column_flow;  /* declared here and passed around to avoid duplicate calculations */

    split_flow = ConvertFlowDcuToIu(flow, status->IU_Scaling );

    flow_display = ConvertFlowIuToDisplay(split_flow, status->IU_Scaling );


    validate = ValidateInletSplitFlow( flow_display, status, &column_flow );

    if ( validate == OK )
    {
        ChangeInletSplitFlow ( split_flow, flow_display, status, column_flow );

    }

    return validate;
}

/**begin_proto**/

UI_ERR ValidateInletSplitFlow ( INT32 flow, pINLET_STATUS status, U_INT32 *column_flow )

/**end_proto**/
{

    U_INT32 iu_scaling;

    switch ( VIGetInletType(status))
    {
         case SS:
         case CIS4:
         case CIS3:
         case PTV:            break;

         case PP:
         case COC:
         case ACI:
         case SIMDIST:
         case MANUAL_SS:
         case MANUAL_PP:
         case MANUAL_ACI:
         case MANUAL_COC:
         case UNKNOWN_INLET:  return INVALID_PARAM;

         case NO_INLET:       return NOT_INSTALLED;
    }

    *column_flow =  CalcTotalColumnFlowNTP ( status->Position,
                             status->Inlet_Pressure_Setpt,
                             GetCurrentOvenTemp(),
                             status->IU_Scaling );

    if ( *column_flow == 0 ) return OK;  /* will just set default split ratio */

    if ( flow > GetMaxSplitFlow( status, *column_flow ) ) return PARAM_TOO_LARGE;
    if ( flow < GetMinSplitFlow( status, *column_flow ) ) return PARAM_TOO_SMALL;




    /* scaling this to inlet scaling results in a loss of percision and the */
    /* final resultant split flow is too low.  So, fake out the scaling to  */
    /* retain an extra digit or two of resolution.                          */

    iu_scaling = status->IU_Scaling * SCALING_SCALE_FACTOR;

    *column_flow =  CalcTotalColumnFlowNTP ( status->Position,
                             status->Inlet_Pressure_Setpt,
                             GetCurrentOvenTemp(),
                             iu_scaling );


    return OK;
}

/**begin_proto**/

void ChangeInletSplitFlow( U_INT32 split_flow, INT32 flow, pINLET_STATUS status, U_INT32 column_flow )

/**end_proto**/
{

    U_INT32 split_ratio;


    if ( column_flow == 0 )
        split_ratio = 100 * SPLIT_RATIO_INTERNAL_SCALE;
    else
        split_ratio = QuadWordMultiplyDivide( split_flow, SPLIT_RATIO_INTERNAL_SCALE * SCALING_SCALE_FACTOR, column_flow );

    status->Wkfile->Split_Ratio = split_ratio;
    status->Slam_Flow_Setpt = TRUE;


    LogSetptChange( status->Position == FRNT_INLET ? F_INLET_SPLIT_FLOW : B_INLET_SPLIT_FLOW, flow, 0 );

    status->Ready.Setpt_Change = TRUE;
}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/* CALLS:                                                              */
/*                                                                     */
/* LIMITATIONS:                                                        */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

INT32 GetInletMinMiserFlow ( pINLET_STATUS status )

/**end_proto**/
{
    (void) status;

         return (15*DISPLAY_F_SCALE);
}

/**begin_proto**/

INT32 GetInletMiserFlow ( pINLET_STATUS status )

/**end_proto**/
{
    return ConvertFlowIuToDisplay ( status->Wkfile->Miser_Flow,
                                    status->IU_Scaling );
}

/**begin_proto**/

INT32 DcGetInletMiserFlow ( pINLET_STATUS status )

/**end_proto**/
{
    return ConvertFlowIuToDcu ( status->Wkfile->Miser_Flow,
                                status->IU_Scaling );
}


/**begin_proto**/

UI_ERR SetInletMiserFlow( INT32 flow, pINLET_STATUS status )

/**end_proto**/
{
    U_INT32 miser_flow;
    UI_ERR  validate;

    miser_flow = ConvertFlowDisplayToIu(flow, status->IU_Scaling );

    validate = ValidateInletMiserFlow( flow, status );
    if ( validate == OK )
    {
        LockResource( &Inst_Status.Pneu.Resource_Lock );

        ChangeInletMiserFlow ( miser_flow, flow, status );

        ReleaseResource( &Inst_Status.Pneu.Resource_Lock );
    }

    return validate;

}

/**begin_proto**/

UI_ERR DcSetInletMiserFlow( INT32 flow, pINLET_STATUS status )

/**end_proto**/
{
    U_INT32 miser_flow;
    INT32   flow_display;
    UI_ERR  validate;

    miser_flow = ConvertFlowDcuToIu(flow, status->IU_Scaling );

    flow_display = ConvertFlowIuToDisplay(miser_flow, status->IU_Scaling );

    validate = ValidateInletMiserFlow( flow_display, status );
    if ( validate == OK )
    {
        ChangeInletMiserFlow ( miser_flow, flow_display, status );
    }

    return validate;

}

/**begin_proto**/

UI_ERR ValidateInletMiserFlow ( INT32 flow, pINLET_STATUS status )

/**end_proto**/
{

     switch ( VIGetInletType(status))
     {
          case SS:
          case CIS3:
          case CIS4:
          case PTV:            break;

          case PP:
          case COC:
          case ACI:
          case SIMDIST:
          case MANUAL_SS:
          case MANUAL_PP:
          case MANUAL_ACI:
          case MANUAL_COC:
          case UNKNOWN_INLET:  return INVALID_PARAM;

          case NO_INLET:       return NOT_INSTALLED;
     }



     if ( flow > GetInletMaxFlow   ( status )) return PARAM_TOO_LARGE;
     if ( flow < GetInletMinMiserFlow(status)) return PARAM_TOO_SMALL;

     return OK;

}

/**begin_proto**/

void ChangeInletMiserFlow ( U_INT32 miser_flow, INT32 flow, pINLET_STATUS status )

/**end_proto**/
{
    status->Wkfile->Miser_Flow = miser_flow;


   LogSetptChange( status->Position == FRNT_INLET ? F_INLET_MISER_FLOW : B_INLET_MISER_FLOW, flow, 0 );

   if ( status->Miser_Mode )  status->Ready.Setpt_Change = TRUE;
}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/* CALLS:                                                              */
/*                                                                     */
/* LIMITATIONS:                                                        */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

INT32 GetInletPurgeFlow ( pINLET_STATUS status )

/**end_proto**/
{
    return ConvertFlowIuToDisplay ( status->Wkfile->Purge_Flow,
                                    status->IU_Scaling );
}

/**begin_proto**/

INT32 DcGetInletPurgeFlow ( pINLET_STATUS status )

/**end_proto**/
{
    return ConvertFlowIuToDcu ( status->Wkfile->Purge_Flow,
                                status->IU_Scaling );
}

/**begin_proto**/

UI_ERR SetInletPurgeFlow( INT32 flow, pINLET_STATUS status )

/**end_proto**/
{
    U_INT32 purge_flow;
    UI_ERR  validate;

    purge_flow = ConvertFlowDisplayToIu(flow, status->IU_Scaling );

    validate = ValidateInletPurgeFlow( flow, status );
    if ( validate == OK )
    {
        LockResource( &Inst_Status.Pneu.Resource_Lock );

        ChangeInletPurgeFlow ( purge_flow, flow, status );

        ReleaseResource( &Inst_Status.Pneu.Resource_Lock );
    }

    return validate;

}

/**begin_proto**/

UI_ERR DcSetInletPurgeFlow( INT32 flow, pINLET_STATUS status )

/**end_proto**/
{
    U_INT32 purge_flow;
    INT32   flow_display;
    UI_ERR  validate;

    purge_flow = ConvertFlowDcuToIu(flow, status->IU_Scaling );

    flow_display = ConvertFlowIuToDisplay(purge_flow, status->IU_Scaling );

    validate = ValidateInletPurgeFlow( flow_display, status );
    if ( validate == OK )
    {
        ChangeInletPurgeFlow ( purge_flow, flow_display, status );
    }

    return validate;

}


/**begin_proto**/

UI_ERR ValidateInletPurgeFlow ( INT32 flow, pINLET_STATUS status )

/**end_proto**/
{

     switch ( VIGetInletType(status))
     {
          case SS:
          case COC:
          case CIS3:
          case CIS4:
          case PTV:            break;

          case PP:
          case ACI:
          case SIMDIST:
          case MANUAL_SS:
          case MANUAL_PP:
          case MANUAL_ACI:
          case MANUAL_COC:
          case UNKNOWN_INLET:  return INVALID_PARAM;

          case NO_INLET:       return NOT_INSTALLED;
     }

     if ( flow > GetInletMaxFlow ( status ) )  return PARAM_TOO_LARGE;
     if ( flow < 0 )                           return PARAM_TOO_SMALL;
     return OK;

}

/**begin_proto**/

void ChangeInletPurgeFlow ( U_INT32 purge_flow, INT32 flow, pINLET_STATUS status )

/**end_proto**/
{
    U_INT16 p_iu;
    U_INT32 column_flow;
    U_INT32 septum_purge_flow;

          p_iu = status->Inlet_Pressure_Setpt;

          septum_purge_flow = CalcSeptumPurgeFlow ( status, p_iu );


          column_flow =  CalcTotalColumnFlowNTP ( status->Position,
                             p_iu,
                             GetCurrentOvenTemp(),
                             status->IU_Scaling );


    status->Wkfile->Purge_Flow = purge_flow;

    status->Wkfile->Total_Inlet_Flow = purge_flow + column_flow + septum_purge_flow;

   LogSetptChange( status->Position == FRNT_INLET ? F_INLET_PURGE_FLOW : B_INLET_PURGE_FLOW, flow, 0 );

   if ( status->Inlet_Purge )  status->Ready.Setpt_Change = TRUE;
}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/* CALLS:                                                              */
/*                                                                     */
/* LIMITATIONS:                                                        */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

INT32 GetInletMiserTime ( pINLET_STATUS status )

/**end_proto**/
{
    return  MilliSecsToTime( status->Wkfile->Miser_Time );
}

/**begin_proto**/

UI_ERR SetInletMiserTime( INT32 time, pINLET_STATUS status )

/**end_proto**/
{
    UI_ERR validate;

    validate = ValidateInletMiserTime( time, status );

    if ( validate == OK )
    {
         LockResource( &Inst_Status.Pneu.Resource_Lock );

         ChangeInletMiserTime ( time, status );

         ReleaseResource( &Inst_Status.Pneu.Resource_Lock );
    }

    return validate;
}

/**begin_proto**/

UI_ERR DcSetInletMiserTime( INT32 time, pINLET_STATUS status )

/**end_proto**/
{
    UI_ERR validate;

    validate = ValidateInletMiserTime( time, status );

    if ( ( validate == OK ) || (validate == MISER_TIME_CONFLICT ))
    {
        ChangeInletMiserTime ( time, status );
        return OK;
    }

    return validate;
}


/**begin_proto**/

UI_ERR ValidateInletMiserTime ( INT32 time, pINLET_STATUS status )


/**end_proto**/
{
     UI_ERR  type_chk;

     switch ( VIGetInletType(status))
     {
          case SS:
          case CIS3:
          case CIS4:
          case PTV:            break;

          case PP:
          case ACI:
          case SIMDIST:
          case COC:
          case MANUAL_SS:
          case MANUAL_PP:
          case MANUAL_ACI:
          case MANUAL_COC:
          case UNKNOWN_INLET:  return INVALID_PARAM;

          case NO_INLET:       return NOT_INSTALLED;
     }

     /* CheckTimeSetpt rtns OK PARAM_TOO_LARGE PARAM_TOO_SMALL     */
     if ( (type_chk=CheckTimeSetpt( time )) != OK ) return type_chk ;
/*   if ( status->Config->Type != VOLATILES ) return OK;         Needless b/c #VI => VITime=0 !!  */
     if ( ( TimeToMilliSecs( time ) > (TIME_SETPT)status->Wkfile->VI_Inj_Time ) || ( 0 == status->Wkfile->VI_Inj_Time ) )  return OK;
     return MISER_TIME_CONFLICT ;

}

/**begin_proto**/

void ChangeInletMiserTime( INT32 time, pINLET_STATUS status )

/**end_proto**/
{
    status->Wkfile->Miser_Time = TimeToMilliSecs( time );

    LogSetptChange( status->Position == FRNT_INLET ? F_INLET_MISER_TIME : B_INLET_MISER_TIME, time, 0 );

    status->Ready.Setpt_Change = TRUE;
}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/* CALLS:                                                              */
/*                                                                     */
/* LIMITATIONS:                                                        */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

INT32 GetInletPurgeTime ( pINLET_STATUS status )

/**end_proto**/
{
    return  MilliSecsToTime( status->Wkfile->Purge_Time );
}
/**begin_proto**/

UI_ERR SetInletPurgeTime( INT32 time, pINLET_STATUS status )

/**end_proto**/
{
    UI_ERR validate;

    validate = ValidateInletPurgeTime( time, status );

    if ( validate == OK )
    {
         LockResource( &Inst_Status.Pneu.Resource_Lock );

         ChangeInletPurgeTime ( time, status );

         ReleaseResource( &Inst_Status.Pneu.Resource_Lock );
    }

    return validate;
}

/**begin_proto**/

UI_ERR DcSetInletPurgeTime( INT32 time, pINLET_STATUS status )

/**end_proto**/
{
    UI_ERR validate;

    validate = ValidateInletPurgeTime( time, status );

    if ( ( validate == OK ) || (validate == PURGE_TIME_CONFLICT ))
    {
        ChangeInletPurgeTime ( time, status );
        return OK;
    }

    return validate;
}


/**begin_proto**/

UI_ERR ValidateInletPurgeTime ( INT32 time, pINLET_STATUS status )

/**end_proto**/
{
     UI_ERR  type_chk;

     switch ( VIGetInletType(status))
     {
          case SS:
          case CIS3:
          case CIS4:
          case COC:
          case MANUAL_SS:
          case MANUAL_COC:
          case PTV:            break;

          case PP:
          case ACI:
          case SIMDIST:
          case MANUAL_PP:
          case MANUAL_ACI:
          case UNKNOWN_INLET:  return INVALID_PARAM;

          case NO_INLET:       return NOT_INSTALLED;
     }

     if ( (type_chk=CheckTimeSetpt( time )) != OK ) return type_chk ;
/*   if ( status->Config->Type != VOLATILES ) return OK;         Needless b/c #VI => VITime=0 !!  */
     if ( ( TimeToMilliSecs( time ) > (TIME_SETPT)status->Wkfile->VI_Inj_Time ) || ( 0 == status->Wkfile->VI_Inj_Time ) )  return OK;
     return PURGE_TIME_CONFLICT;

}

/**begin_proto**/

void ChangeInletPurgeTime( INT32 time, pINLET_STATUS status )

/**end_proto**/
{
    status->Wkfile->Purge_Time = TimeToMilliSecs( time );

    LogSetptChange( status->Position == FRNT_INLET ? F_INLET_PURGE_TIME : B_INLET_PURGE_TIME, time, 0 );

    status->Ready.Setpt_Change = TRUE;
}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

INT32 GetVentPressure ( pINLET_STATUS status )

/**end_proto**/
{

       return ConvertPresIuToDisplay ( status->Wkfile->Vent_Pressure, status->Dcm2_Per_IU );
}

/**begin_proto**/

INT32 DcGetVentPressure ( pINLET_STATUS status )

/**end_proto**/
{

       return ConvertPresIuToDcu ( status->Wkfile->Vent_Pressure, status->Dcm2_Per_IU );
}


/**begin_proto**/

UI_ERR  SetVentPressure( INT32 setpt, pINLET_STATUS status )

/**end_proto**/
{

    U_INT32  p_iu;
    UI_ERR   validate;

    p_iu = ConvertPresDisplayToIu(setpt, status->Dcm2_Per_IU );

    validate = ValidateVentPres( setpt, status );

    if ( validate == OK )
    {
         LockResource( &Inst_Status.Pneu.Resource_Lock );

         ChangeVentPressure ( p_iu, setpt, status );

         ReleaseResource( &Inst_Status.Pneu.Resource_Lock );
    }

    return validate;

}

/**begin_proto**/

UI_ERR DcSetVentPressure( INT32 setpt, pINLET_STATUS status )

/**end_proto**/
{

    U_INT32  p_iu;
    UI_ERR   validate;
    INT32    p_display;

    p_iu = ConvertPresDcuToIu(setpt, status->Dcm2_Per_IU );

    p_display = ConvertPresIuToDisplay(p_iu, status->Dcm2_Per_IU );

    validate = ValidateVentPres( p_display, status );

    if ( validate == OK )
    {
         ChangeVentPressure ( p_iu, p_display, status );
    }

    return validate;

}


/**begin_proto**/

UI_ERR ValidateVentPres ( INT32 pres, pINLET_STATUS status )

/**end_proto**/
{
     switch ( status->Config->Type )
     {
          case PTV:
          case CIS3:
          case CIS4:
                               break;
          case SS:
          case COC:
          case MANUAL_SS:
          case MANUAL_COC:
          case PP:
          case ACI:
          case SIMDIST:
          case VOLATILES:
          case MANUAL_PP:
          case MANUAL_ACI:
          case UNKNOWN_INLET:  return INVALID_PARAM;

          case NO_INLET:       return NOT_INSTALLED;
     }

     if ( status->Wkfile->Injection_Mode != SOLVENT_VENT )
     {
           return INVALID_PARAM;
     }

     return ValidateInletPresSetpt( pres, status );

}

/**begin_proto**/

void ChangeVentPressure ( U_INT16 pres, INT32 setpt, pINLET_STATUS status )

/**end_proto**/
{

    status->Wkfile->Vent_Pressure =  pres;

    if ( CheckForSolventVent( status ) == TRUE ) SlamInletPresSetpt( pres, status );

    LogSetptChange( status->Position == FRNT_INLET ? F_INLET_VENT_PRES : B_INLET_VENT_PRES, setpt, (INT32)GetPresUnits());

    status->Ready.Setpt_Change = TRUE;

    (void) setpt;
}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/* CALLS:                                                              */
/*                                                                     */
/* LIMITATIONS:                                                        */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

INT32  GetVentTime ( pINLET_STATUS status )

/**end_proto**/
{
    return  MilliSecsToTime( status->Wkfile->Vent_Time );
}

/**begin_proto**/

UI_ERR ValidateVentTime ( INT32 time, pINLET_STATUS status )

/**end_proto**/
{
     switch ( status->Config->Type )
     {
          case CIS3:
          case CIS4:
          case PTV:            break;

          case SS:
          case COC:
          case MANUAL_SS:
          case MANUAL_COC:
          case PP:
          case ACI:
          case SIMDIST:
          case MANUAL_PP:
          case MANUAL_ACI:
          case UNKNOWN_INLET:  return INVALID_PARAM;

          case NO_INLET:       return NOT_INSTALLED;
     }

     return CheckTimeSetpt( time );
}


/**begin_proto**/

UI_ERR SetVentTime( INT32 time, pINLET_STATUS status )

/**end_proto**/
{
    UI_ERR validate;

    validate = ValidateVentTime( time, status );

    if ( validate == OK )
    {
        LockResource( &Inst_Status.Pneu.Resource_Lock );

        ChangeVentTime ( time, status );

        ReleaseResource( &Inst_Status.Pneu.Resource_Lock );
    }

    return validate;
}



/**begin_proto**/

UI_ERR DcSetVentTime( INT32 time, pINLET_STATUS status )

/**end_proto**/
{
    UI_ERR validate;

    validate = ValidateVentTime( time, status );

    if ( validate == OK )
    {
        ChangeVentTime ( time, status );
    }

    return validate;
}


/**begin_proto**/

void ChangeVentTime( INT32 time, pINLET_STATUS status )

/**end_proto**/
{

    status->Wkfile->Vent_Time = TimeToMilliSecs( time );

    LogSetptChange( status->Position == FRNT_INLET ? F_INLET_VENT_TIME : B_INLET_VENT_TIME, time, 0 );

    status->Ready.Setpt_Change = TRUE;
}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/* CALLS:                                                              */
/*                                                                     */
/* LIMITATIONS:                                                        */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

INT32 GetInletVentFlow ( pINLET_STATUS status )

/**end_proto**/
{
    return ConvertFlowIuToDisplay ( status->Wkfile->Vent_Flow,
                                    status->IU_Scaling );
}

/**begin_proto**/

INT32 DcGetInletVentFlow ( pINLET_STATUS status )

/**end_proto**/
{
    return ConvertFlowIuToDcu ( status->Wkfile->Vent_Flow,
                                status->IU_Scaling );
}

/**begin_proto**/

UI_ERR SetInletVentFlow( INT32 flow, pINLET_STATUS status )

/**end_proto**/
{
    U_INT32 purge_flow;
    UI_ERR  validate;

    purge_flow = ConvertFlowDisplayToIu(flow, status->IU_Scaling );

    validate = ValidateInletVentFlow( flow, status );
    if ( validate == OK )
    {
        LockResource( &Inst_Status.Pneu.Resource_Lock );

        ChangeInletVentFlow ( purge_flow, flow, status );

        ReleaseResource( &Inst_Status.Pneu.Resource_Lock );
    }

    return validate;

}

/**begin_proto**/

UI_ERR DcSetInletVentFlow( INT32 flow, pINLET_STATUS status )

/**end_proto**/
{
    U_INT32 vent_flow;
    INT32   flow_display;
    UI_ERR  validate;

    vent_flow = ConvertFlowDcuToIu(flow, status->IU_Scaling );

    flow_display = ConvertFlowIuToDisplay(vent_flow, status->IU_Scaling );

    validate = ValidateInletVentFlow( flow_display, status );
    if ( validate == OK )
    {
        ChangeInletVentFlow ( vent_flow, flow_display, status );
    }

    return validate;

}


/**begin_proto**/

UI_ERR ValidateInletVentFlow ( INT32 flow, pINLET_STATUS status )

/**end_proto**/
{

     switch ( status->Config->Type )
     {
          case CIS3:
          case CIS4:
          case PTV:            break;

          case SS:
          case COC:
          case PP:
          case ACI:
          case SIMDIST:
          case MANUAL_SS:
          case MANUAL_PP:
          case MANUAL_ACI:
          case MANUAL_COC:
          case UNKNOWN_INLET:  return INVALID_PARAM;

          case NO_INLET:       return NOT_INSTALLED;
     }

     if ( flow > GetInletMaxFlow ( status ) )  return PARAM_TOO_LARGE;
     if ( flow < 0 )                           return PARAM_TOO_SMALL;
     return OK;

}

/**begin_proto**/

void ChangeInletVentFlow ( U_INT32 vent_flow, INT32 flow, pINLET_STATUS status )

/**end_proto**/
{

   status->Wkfile->Vent_Flow = vent_flow;

   LogSetptChange( status->Position == FRNT_INLET ? F_INLET_VENT_FLOW : B_INLET_VENT_FLOW, flow, 0 );

   if ( status->Inlet_Purge )  status->Ready.Setpt_Change = TRUE;

   (void)flow;
}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/* CALLS:                                                              */
/*                                                                     */
/* LIMITATIONS:                                                        */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

UI_ERR VITypeCheck ( pINLET_STATUS statis )

/**end_proto**/
{

     switch ( statis->Config->Type )
     {
          case VOLATILES:   return OK;

          default:
          case CIS3:
          case CIS4:
          case PTV:
          case SS:
          case COC:
          case PP:
          case ACI:
          case SIMDIST:
          case MANUAL_SS:
          case MANUAL_PP:
          case MANUAL_ACI:
          case MANUAL_COC:
          case UNKNOWN_INLET:  return INVALID_PARAM;

          case NO_INLET:       return NOT_INSTALLED;
     }

}

/**begin_proto**/

INT32  GetVIInjTime ( pINLET_STATUS status )

/**end_proto**/
{
    return  MilliSecsToTime( status->Wkfile->VI_Inj_Time );
}

/**begin_proto**/

INT32  DcGetVIInjTime ( pINLET_STATUS status )

/**end_proto**/
{
    return  MilliSecsToTime(
                             GetInletInjectMode(status) == SPLIT ? status->Wkfile->VI_Inj_Time_Save :
                                                                   status->Wkfile->VI_Inj_Time
                           );
}

/**begin_proto**/

UI_ERR ValidateVIInjTime ( INT32 time, pINLET_STATUS status )

/**end_proto**/

{
     UI_ERR  type_chk;
     INT32   pneu_time1;
     pCOLUMN_STATUS col_status;

     if ( (type_chk=VITypeCheck( status )) != OK ) return type_chk ;

     if ( (type_chk=CheckTimeSetpt( time )) != OK ) return type_chk ;

     pneu_time1 = 0x7fffffff ;
     if ((time = TimeToMilliSecs( time )) == 0 ) return OK ;

     if ( status->Wkfile->Injection_Mode == SPLIT ) return OK ; /* assumes time will go to VIInjTimeSave & 0->VIInjTime */

     col_status = Inst_Config.Pneu.Column_1.Source == status->Position ? /* Position = FRNT_INLET or BACK_INLET */
                  &Inst_Status.Pneu.Column_1 :
                  &Inst_Status.Pneu.Column_2  ; /* assume that if not col1 then col2 */

     if (
         (DoingMethodInstall()==0                                     ) &&
         (GetColumnSource(col_status ) == status->Position       ) &&  /* this line verifies above assumption ! */
         ( (GetColumnControlMode(col_status) == RAMP_PRES ) ||
           (GetColumnControlMode(col_status) == RAMP_FLOW     )  )
        )
     {
        pneu_time1 = GetRampInitTime( (pRAMPINFO)(col_status->Ramp_Info) ) ; /* here iff good assumption & ramping */
     };

     if (time >= pneu_time1 ) return COL_TIME1_CONFLICT ;

     if ( status->Wkfile->Injection_Mode == DIRECT ) return OK;

     /* in SPLITLESS if we get here ... */

     if ( (InletHasColumn(status)) && ( ON == status->Wkfile->Miser_Mode) && (time >= status->Wkfile->Miser_Time  ) )
        return MISER_TIME_CONFLICT ;

/*   if ( status->Wkfile->Injection_Mode == SPLIT ) return OK;  deleted b/c redundant */

     if (time < status->Wkfile->Purge_Time  ) return OK;
     return PURGE_TIME_CONFLICT ;
}

/**begin_proto**/

UI_ERR SetVIInjTime( INT32 time, pINLET_STATUS status )

/**end_proto**/
{
    UI_ERR validate;

    validate = ValidateVIInjTime( time, status );

    if ( validate == OK )
    {
        LockResource( &Inst_Status.Pneu.Resource_Lock );

        ChangeVIInjTime ( time, status );

        ReleaseResource( &Inst_Status.Pneu.Resource_Lock );
    }

    return validate;
}

/**begin_proto**/

void   FixVIPurgeTime( pINLET_STATUS status )

/**end_proto**/
{
  INT32 tym ;

    if ((tym =  GetVIInjTime( status ) ) ==0      ) return;
    if (tym < GetInletPurgeTime(status)           ) return;
    ++tym ;
    ChangeInletPurgeTime ( tym, status ); /* Note that ChangeInletPurgeTime call LogSetptChange ! */
    SetNewException(status->Position==FRNT_INLET? FINL_PURG_TIME_CONFLICT : BINL_PURG_TIME_CONFLICT, tym ,0);
    ClearNewException(status->Position==FRNT_INLET? FINL_PURG_TIME_CONFLICT : BINL_PURG_TIME_CONFLICT);
}

/**begin_proto**/

UI_ERR DcSetVIInjTime( INT32 time, pINLET_STATUS status )

/**end_proto**/
{
    UI_ERR validate;

    validate = ValidateVIInjTime( time, status );

    if ( validate == OK )
    {
        if (GetInletInjectMode(status) == SPLIT )
        {
           status->Wkfile->VI_Inj_Time_Save = TimeToMilliSecs( time );
           time = 0 ;
        };
        ChangeVIInjTime ( time, status );
    }
    else
    {
        FixMiserTime(status); /* to ensure dont leave inconsistent data */
        if (GetInletInjectMode(status) == SPLITLESS  ) FixVIPurgeTime(status); /* ensure consistent data */
    }

    return validate;
}


/**begin_proto**/

void ChangeVIInjTime( INT32 time, pINLET_STATUS status )

/**end_proto**/
{

    status->Wkfile->VI_Inj_Time = TimeToMilliSecs( time );

    LogSetptChange( status->Position == FRNT_INLET ? F_INLET_VI_INJ_TIME : B_INLET_VI_INJ_TIME, time, 0 );

    status->Ready.Setpt_Change = TRUE;
}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/* CALLS:                                                              */
/*                                                                     */
/* LIMITATIONS:                                                        */
/*                                                                     */
/***********************************************************************/


/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

INT32 GetPressurePulsePressure ( pINLET_STATUS status )

/**end_proto**/
{

       return ConvertPresIuToDisplay ( status->Wkfile->Pressure_Pulse_Pressure, status->Dcm2_Per_IU );
}

/**begin_proto**/

INT32 DcGetPressurePulsePressure ( pINLET_STATUS status )

/**end_proto**/
{

       return ConvertPresIuToDcu ( status->Wkfile->Pressure_Pulse_Pressure, status->Dcm2_Per_IU );
}


/**begin_proto**/

UI_ERR  SetPressurePulsePressure( INT32 setpt, pINLET_STATUS status )

/**end_proto**/
{

    U_INT32  p_iu;
    UI_ERR   validate;

    p_iu = ConvertPresDisplayToIu(setpt, status->Dcm2_Per_IU );

    validate = ValidatePressurePulsePres( setpt, status );

    if ( validate == OK )
    {
         LockResource( &Inst_Status.Pneu.Resource_Lock );

         ChangePressurePulsePressure ( p_iu, setpt, status );

         ReleaseResource( &Inst_Status.Pneu.Resource_Lock );
    }

    return validate;

}

/**begin_proto**/

UI_ERR DcSetPressurePulsePressure( INT32 setpt, pINLET_STATUS status )

/**end_proto**/
{

    U_INT32  p_iu;
    UI_ERR   validate;
    INT32    p_display;

    p_iu = ConvertPresDcuToIu(setpt, status->Dcm2_Per_IU );

    p_display = ConvertPresIuToDisplay(p_iu, status->Dcm2_Per_IU );

    validate = ValidatePressurePulsePres( p_display, status );

    if ( validate == OK )
    {
         ChangePressurePulsePressure ( p_iu, p_display, status );
    }

    return validate;

}


/**begin_proto**/

UI_ERR ValidatePressurePulsePres ( INT32 pres, pINLET_STATUS status )

/**end_proto**/
{
     switch ( status->Config->Type )
     {
          case SS:
          case PTV:
          case CIS3:
          case CIS4:
                               break;
          case COC:
          case MANUAL_SS:
          case MANUAL_COC:
          case VOLATILES:
          case PP:
          case ACI:
          case SIMDIST:
          case MANUAL_PP:
          case MANUAL_ACI:
          case UNKNOWN_INLET:  return INVALID_PARAM;

          case NO_INLET:       return NOT_INSTALLED;
     }

     if (( status->Wkfile->Injection_Mode != SPLITLESS_PULSED ) && ( status->Wkfile->Injection_Mode != SPLIT_PULSED ))
     {
           return INVALID_PARAM;
     }

     return ValidateInletPresSetpt( pres, status );

}

/**begin_proto**/

void ChangePressurePulsePressure ( U_INT16 pres, INT32 setpt, pINLET_STATUS status )

/**end_proto**/
{

    status->Wkfile->Pressure_Pulse_Pressure =  pres;
    if ( CheckForPressurePulse( status ) == TRUE ) SlamInletPresSetpt( pres, status );

    LogSetptChange( status->Position == FRNT_INLET ? F_INLET_PULSE_PRES : B_INLET_PULSE_PRES, setpt, (INT32)GetPresUnits());

    status->Ready.Setpt_Change = TRUE;
}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/* CALLS:                                                              */
/*                                                                     */
/* LIMITATIONS:                                                        */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

INT32 GetPressurePulseTime ( pINLET_STATUS status )

/**end_proto**/
{
    return  MilliSecsToTime( status->Wkfile->Pulse_Time );
}

/**begin_proto**/

UI_ERR ValidatePressurePulseTime ( INT32 time, pINLET_STATUS status )

/**end_proto**/
{
     switch ( status->Config->Type )
     {
          case SS:
          case COC:
          case MANUAL_SS:
          case MANUAL_COC:
          case CIS3:
          case CIS4:
          case PTV:            break;

          case VOLATILES:
          case PP:
          case ACI:
          case SIMDIST:
          case MANUAL_PP:
          case MANUAL_ACI:
          case UNKNOWN_INLET:  return INVALID_PARAM;

          case NO_INLET:       return NOT_INSTALLED;
     }

     return CheckTimeSetpt( time );
}


/**begin_proto**/

UI_ERR SetPressurePulseTime( INT32 time, pINLET_STATUS status )

/**end_proto**/
{
    UI_ERR validate;

    validate = ValidatePressurePulseTime( time, status );

    if ( validate == OK )
    {
        LockResource( &Inst_Status.Pneu.Resource_Lock );

        ChangePressurePulseTime ( time, status );

        ReleaseResource( &Inst_Status.Pneu.Resource_Lock );
    }

    return validate;
}



/**begin_proto**/

UI_ERR DcSetPressurePulseTime( INT32 time, pINLET_STATUS status )

/**end_proto**/
{
    UI_ERR validate;

    validate = ValidatePressurePulseTime( time, status );

    if ( validate == OK )
    {
        ChangePressurePulseTime ( time, status );
    }

    return validate;
}


/**begin_proto**/

void ChangePressurePulseTime( INT32 time, pINLET_STATUS status )

/**end_proto**/
{

    status->Wkfile->Pulse_Time = TimeToMilliSecs( time );

    LogSetptChange( status->Position == FRNT_INLET ? F_INLET_PULSE_TIME : B_INLET_PULSE_TIME, time, 0 );

    status->Ready.Setpt_Change = TRUE;
}


/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/* CALLS:                                                              */
/*                                                                     */
/* LIMITATIONS:                                                        */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

INT32 GetInletSplitRatio ( pINLET_STATUS status )

/**end_proto**/
{
    return  QuadWordMultiplyDivide( status->Wkfile->Split_Ratio, SPLIT_RATIO_UI_SCALE, SPLIT_RATIO_INTERNAL_SCALE );
}
/**begin_proto**/

INT32 GetMaxSplitRatioIu ( pINLET_STATUS status )

/**end_proto**/
{
#if 0
     U_INT32 split_ratio;
     U_INT32 column_flow;
     U_INT32 max_inlet_flow;
     U_INT32 septum_flow;
     U_INT16 Pi;
     BIT8    capped;

     Pi = status->Wkfile->Inlet_Pressure;

     septum_flow = CalcSeptumPurgeFlow( status, Pi );

     column_flow =  CalcTotalColumnFlowNTP ( status->Position,
                             Pi,
                             GetCurrentOvenTemp(),
                             status->IU_Scaling );


     max_inlet_flow = GetInletMaxFlowIu ( status, status->IU_Scaling );

     if ( max_inlet_flow < ( column_flow + septum_flow ) )
     {
          return  GetMinSplitRatio( status );
     }
     else
     {
          split_ratio = BoundsCheckedQWMD( (max_inlet_flow - column_flow - septum_flow),
                                           SPLIT_RATIO_INTERNAL_SCALE,
                                           column_flow,
                                           (MAX_SPLIT_RATIO * SPLIT_RATIO_INTERNAL_SCALE ),
                                           &capped );
     }



     return split_ratio;
#else
     (void)status;

     return MAX_SPLIT_RATIO * SPLIT_RATIO_INTERNAL_SCALE;

#endif

}
/**begin_proto**/

INT32 GetMaxSplitRatio ( pINLET_STATUS status )

/**end_proto**/
{

     return QuadWordMultiplyDivide( GetMaxSplitRatioIu( status ), SPLIT_RATIO_UI_SCALE, SPLIT_RATIO_INTERNAL_SCALE );

}

/**begin_proto**/

INT32 GetMinSplitRatio( pINLET_STATUS status )

/**end_proto**/
{
     (void)status;
     return QuadWordMultiplyDivide ( MIN_SPLIT_RATIO_IU, SPLIT_RATIO_UI_SCALE, SPLIT_RATIO_INTERNAL_SCALE );
}

/**begin_proto**/

INT32 DcGetInletSplitRatio ( pINLET_STATUS status )

/**end_proto**/
{
    return  QuadWordMultiplyDivide( status->Wkfile->Split_Ratio, SPLIT_RATIO_DC_SCALE, SPLIT_RATIO_INTERNAL_SCALE );
}

/**begin_proto**/

UI_ERR ValidateInletSplitRatio ( INT32 split_ratio, pINLET_STATUS status )

/**end_proto**/
{

     if ( split_ratio < MIN_SPLIT_RATIO_IU )           return PARAM_TOO_SMALL;
     if ( split_ratio > GetMaxSplitRatioIu( status ) ) return PARAM_TOO_LARGE;

     return OK;
}


/**begin_proto**/

UI_ERR SetInletSplitRatio( INT32 split_ratio, pINLET_STATUS status )

/**end_proto**/
{
    UI_ERR validate;
    U_INT32 split_ratio_iu;

    split_ratio_iu = QuadWordMultiplyDivide( split_ratio, SPLIT_RATIO_INTERNAL_SCALE, SPLIT_RATIO_UI_SCALE );

    validate = ValidateInletSplitRatio( split_ratio_iu, status );

    if ( validate == OK )
    {
       LockResource ( &Inst_Status.Pneu.Resource_Lock );

       ChangeInletSplitRatio ( split_ratio_iu, split_ratio, status );

       ReleaseResource( &Inst_Status.Pneu.Resource_Lock );
    }

    return validate;
}

/**begin_proto**/

UI_ERR DcSetInletSplitRatio( INT32 split_ratio, pINLET_STATUS status )

/**end_proto**/
{
    UI_ERR validate;
    U_INT32 split_ratio_iu;
    INT32   split_ratio_display;

    split_ratio_iu = QuadWordMultiplyDivide( split_ratio, SPLIT_RATIO_INTERNAL_SCALE, SPLIT_RATIO_DC_SCALE );

    split_ratio_display = QuadWordMultiplyDivide( split_ratio, SPLIT_RATIO_UI_SCALE, SPLIT_RATIO_INTERNAL_SCALE );

    validate = ValidateInletSplitRatio( split_ratio_iu, status );

    if ( validate == OK )
    {
       ChangeInletSplitRatio ( split_ratio_iu, split_ratio_display, status );
    }

    return validate;
}

/**begin_proto**/

void ChangeInletSplitRatio ( U_INT32 split_ratio, INT32 split_ratio_display, pINLET_STATUS status )

/**end_proto**/
{

    status->Wkfile->Split_Ratio = split_ratio;
    status->Slam_Flow_Setpt = TRUE;
    status->Ready.Setpt_Change = TRUE;

    LogSetptChange( status->Position == FRNT_INLET ? F_INLET_SPLIT_RATIO : B_INLET_SPLIT_RATIO, split_ratio_display, 0 );

}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

ON_OFF GetInletState ( pINLET_STATUS status )

/**end_proto**/
{

      if ( status->Shutdown ) return SHUTDOWN;

      return ( status->Config->Functional &&  ( status->Wkfile->On_Off == ON ) ) ? ON : OFF;

}

/**begin_proto**/

ON_OFF GetInletWkfileState ( pINLET_STATUS status )

/**end_proto**/
{

      return ( status->Config->Functional && ( status->Wkfile->On_Off == ON ) ) ? ON : OFF;

}

/**begin_proto**/

UI_ERR DcSetInletState ( ON_OFF state, pINLET_STATUS status )

/**end_proto**/
{
    BIT8 setpt_changed;

    setpt_changed = (GetInletState ( status ) != state );
    ChangeInletState( state, status );

    if (setpt_changed)
    {
       LogInletStateChange( state, status );
    }

    return OK;
}



/**begin_proto**/

UI_ERR SetInletState ( ON_OFF state, pINLET_STATUS status )

/**end_proto**/
{
    BIT8 setpt_changed;
 /* revisit */

    LockResource( &Inst_Status.Pneu.Resource_Lock );

    setpt_changed = (GetInletState ( status ) != state );
    ChangeInletState( state, status );

    ReleaseResource( &Inst_Status.Pneu.Resource_Lock );

    if (setpt_changed)
    {
       LogInletStateChange( state, status );
    }

    return OK;
}


/**begin_proto**/

void LogInletStateChange ( ON_OFF state, pINLET_STATUS status )

/**end_proto**/
{


    /* this really sucks, there should only be one set routine for this.  It is done this way to match */
    /* with the way everything else does on/off transitions.                                           */

    if ( (( status->Config->Type != PP ) &&( status->Config->Type != ACI ) && ( status->Config->Type != SIMDIST ))
                                                                                         || ( status->Has_Column ) )
    {
         if ( state == ON )
         {
             LogSetptChange( status->Position == FRNT_INLET ? F_INLET_PRES_ON : B_INLET_PRES_ON, 0, 0 );
         }
         else
         {
             LogSetptChange( status->Position == FRNT_INLET ? F_INLET_PRES_OFF : B_INLET_PRES_OFF, 0, 0 );
         }
    }
    else
    {
         if ( state == ON )
         {
             LogSetptChange( status->Position == FRNT_INLET ? F_INLET_FLOW_ON : B_INLET_FLOW_ON, 0, 0 );
         }
         else
         {
             LogSetptChange( status->Position == FRNT_INLET ? F_INLET_FLOW_OFF : B_INLET_FLOW_OFF, 0, 0 );
         }
    }

}



/**begin_proto**/

void ChangeInletState ( ON_OFF state, pINLET_STATUS status )

/**end_proto**/
{

    if (( state == ON ) || ( state == OFF ))  status->Wkfile->On_Off = state;

    if ( state == OFF )
    {
        status->Filtered_Inlet_Pressure_Setpt   = 0;
        status->Filtered_Total_Inlet_Flow_Setpt = 0;
    }
    else
    {
        status->Ready.Inlet_On = TRUE;
    }

    status->Wkfile->On_Off = state;


    if ( status->Position == FRNT_INLET )
    {
          if (status->Shutdown)
          {
              if ( state == OFF )
              {
                   /* pcb requires restart to disable safety shutdown mode */
                   /* for any channel.  We want to make sure that the value*/
                   /* for any control loops is 0 (off) before pcb gets the */
                   /* restart request for an OFF value.                    */
                   Inst_Status.Pneu.Frnt_Inlet.Pres_Adc_Setpt = 0;
                   Inst_Status.Pneu.Frnt_Inlet.Flow_Adc_Setpt = 0;
                   DownloadSetpoints();
              }

              QuickRestartChannel( FRNT_INLET_PRESSURE_MASK | FRNT_INLET_FLOW_MASK, 3 );
          }
          ClearNewException( FRNT_INLET_PRES_SHUTDOWN );
          ClearNewException( FRNT_INLET_FLOW_SHUTDOWN );
    }
    else
    {
          if (status->Shutdown )
          {
              if ( state == OFF )
              {
                   /* pcb requires restart to disable safety shutdown mode */
                   /* for any channel.  We want to make sure that the value*/
                   /* for any control loops is 0 (off) before pcb gets the */
                   /* restart request for an OFF value.                    */
                   Inst_Status.Pneu.Back_Inlet.Pres_Adc_Setpt = 0;
                   Inst_Status.Pneu.Back_Inlet.Flow_Adc_Setpt = 0;
                   DownloadSetpoints();
              }

              QuickRestartChannel( BACK_INLET_PRESSURE_MASK | BACK_INLET_FLOW_MASK, 3 );
          }
          ClearNewException( BACK_INLET_PRES_SHUTDOWN );
          ClearNewException( BACK_INLET_FLOW_SHUTDOWN );
    }

    status->Shutdown = FALSE;

    status->Ready.Setpt_Change = TRUE;

}


/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

INLET_TYPE GetInletType( pINLET_STATUS status)

/**end_proto**/
{

       return status->Config->Type;

}

/**begin_proto**/

BIT8 GenSS( pINLET_STATUS status)

/**end_proto**/

{

   switch( status->Config->Type)
   {
   case VOLATILES:
   case SS:
   case CIS3:
   case CIS4:
      return 1;

   default:
      return 0;
   }
}

/**begin_proto**/

INLET_TYPE VIGetInletType( pINLET_STATUS status)

/**end_proto**/
{
     INLET_TYPE HWType;

     HWType = status->Config->Type;
     if ( HWType != VOLATILES) return HWType;

     if ( GetVISplitPort(status)  == PLUMBED )
     return  SS;
     else
/*   return UNKNOWN_INLET ; */
     return PP ;

}

#ifdef SUPPORT_UNSUPPORTED_INLET_TYPES

/**begin_proto**/

INLET_TYPE GetHonestInletType( pINLET_STATUS status)

/**end_proto**/
{

       return status->Config->True_Type;

}

#endif

/**begin_proto**/

INLET_TYPE GetInletBaseType ( pINLET_STATUS status )

/**end_proto**/
{

     switch ( status->Config->Type )   /* revisit for VOLATILES ??? */
     {
        case SS:
        case MANUAL_SS:  return SS;
        case PP:
        case MANUAL_PP:  return PP;
        case COC:
        case MANUAL_COC: return COC;
        case MANUAL_ACI:
        case ACI:        return UNKNOWN_INLET;    /* mapped to COC; assert should never get here */
        case SIMDIST:    return PP;
        case PTV:        return UNKNOWN_INLET;    /* never used;    assert should never get here */
        case G_PTV:      return UNKNOWN_INLET;    /* mapped to SS ; assert should never get here */
        case CIS3:       return PTV;
        case CIS4:       return PTV;
     }

     return status->Config->Type;
}
/***********************************************************************/
/* FUNCTION:  SetInletType                                             */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:  To set the inlet type                                     */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/* CALLS:                                                              */
/*                                                                     */
/* LIMITATIONS:                                                        */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

UI_ERR ValidateInletType( pINLET_STATUS status, INLET_TYPE type )

/**end_proto**/
{

     POSITION p;

     if ( ModuleExists( status->Module_Number ))  return NOT_ALLOWED;

     p = status->Position == FRNT_INLET ? FRONT : BACK ;

     switch ( type )
     {
         case NO_INLET:if (GetTempZonePresence(InletZonePtr(p)) == ZONE_PRESENT)
                       {
                          return NOT_ALLOWED;
                       }

                        /* intentional fall through */

         case UNKNOWN_INLET:
         case MANUAL_SS:
         case MANUAL_PP:
         case MANUAL_ACI:
         case MANUAL_COC:  return OK;

     }

     return INVALID_PARAM;

}

/**begin_proto**/

UI_ERR SetInletType( pINLET_STATUS status, INLET_TYPE type )

/**end_proto**/
{
   UI_ERR  error;


   if (( error = ValidateInletType( status, type )) != OK ) return error;

   INTERRUPTS_OFF

   status->Config->Type = type;

   if ( status->Config->Type == MANUAL_ACI )
   {
       status->Config->True_Type = MANUAL_ACI;
       status->Config->Type      = MANUAL_COC;
   }
   else
   {
       status->Config->True_Type = status->Config->Type;
   }

   INTERRUPTS_ON

   /* Finally, reconfigure the thermal zone if necessary */

   if ( status == &Inst_Status.Pneu.Frnt_Inlet )
   {
      if ( type != (INLET_TYPE) GetZoneType(pFRONT_INLET_TEMP) )
      {
         DetermineInletZoneConfig( type, pFRONT_INLET_TEMP);
      }
   }
   else
   {
      if ( type != (INLET_TYPE) GetZoneType(pBACK_INLET_TEMP) )
      {
         DetermineInletZoneConfig( type, pBACK_INLET_TEMP);
      }
   }

   LogSetptChange( status->Position == FRNT_INLET ? F_INLET_TYPE : B_INLET_TYPE, (INT32)type, 0 );

   return OK;
}

/**begin_proto**/

BIT8 EpcInletChk ( pINLET_STATUS status2 )

/**end_proto**/
{

    if (( status2->Config->Type == PP     )   ||
        ( status2->Config->Type == SS     )   ||
        ( status2->Config->Type == COC    )   ||
        ( status2->Config->Type == JIB    )   ||
        ( status2->Config->Type == ACI    )   ||
        ( status2->Config->Type == SIMDIST)   ||
        ( status2->Config->Type == VOLATILES) ||
        ( status2->Config->Type == PTV    )   ||
        ( status2->Config->Type == CIS4   )   ||
        ( status2->Config->Type == CIS3   )    )
    {
        return TRUE;
    }
    else
    {
        return FALSE;
    }
}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

BIT8 EpcInlet ( pINLET_STATUS status )

/**end_proto**/
{

    if ( !status->Config->Functional ) return FALSE; /* dead inlet */
    if ( EpcInletChk(status) )
    {
        return TRUE ;
    }
    else
    {
        return FALSE ;
    }
}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

INT32 GetInletMaxPres( pINLET_STATUS status )

/**end_proto**/
{

   return ConvertPresIuToDisplay ( status->P_Sensor_Range, status->Dcm2_Per_IU );
}

/**begin_proto**/

INT32 GetInletMaxFlow( pINLET_STATUS status )

/**end_proto**/
{

   return ConvertFlowIuToDisplay ( GetInletMaxFlowIu ( status, status->IU_Scaling ), status->IU_Scaling );
}

/**begin_proto**/

INT32 GetInletMaxPresIu( pINLET_STATUS status, U_INT16 dcm2_per_iu )

/**end_proto**/
{

   return QuadWordMultiplyDivide( status->P_Sensor_Range, dcm2_per_iu, status->Dcm2_Per_IU );
}


/**begin_proto**/

INT32 GetInletRealMaxPresIu( pINLET_STATUS status, U_INT16 dcm2_per_iu )

/**end_proto**/
{

   return QuadWordMultiplyDivide( status->Real_PS_Range, dcm2_per_iu, status->Dcm2_Per_IU );
}


/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

INT32 DcGetInletCalPresGain ( pINLET_STATUS status )

/**end_proto**/
{

    if ( !EpcInlet( status ) ) return 0;

    return SignedQuadWordMultiplyDivide( CALIB_GAIN_DC_SCALE,
                                         status->Calib.P_Sensor_Gain - CALIB_GAIN_SCALING,
                                         CALIB_GAIN_SCALING );
}

/**begin_proto**/

INT32 GetInletCalPresZero ( pINLET_STATUS status )

/**end_proto**/
{

    pPRES_SENSOR_STRUCT sensor;
    U_INT16 temp;

    if ( !EpcInlet( status ) ) return 0;

    sensor = &status->Tcomp_Tables->Pres_Sensor;
    temp   =  status->Tcomp_Tables->Thermistor.Module_Temperature;

    return GetPresOffsetDispUnits ( status->Calib.P_Sensor_Offset, status->Dcm2_Per_IU, sensor, temp );

}

/**begin_proto**/

INT32 DcGetInletCalPresZero ( pINLET_STATUS status )

/**end_proto**/
{

    pPRES_SENSOR_STRUCT sensor;
    U_INT16 temp;

    if ( !EpcInlet( status ) ) return 0;

    sensor = &status->Tcomp_Tables->Pres_Sensor;
    temp   =  status->Tcomp_Tables->Thermistor.Module_Temperature;

    return GetPresOffsetDcUnits ( status->Calib.P_Sensor_Offset, status->Dcm2_Per_IU, sensor, temp );

}

/**begin_proto**/

UI_ERR SetInletCalPresZero ( pINLET_STATUS status )

/**end_proto**/
{
      UI_ERR error;

      if ( !EpcInlet(status) ) return NOT_ALLOWED;

      LockResource ( &Inst_Status.Pneu.Resource_Lock );

      error = ChangeInletCalPresZero( status );

      ReleaseResource ( &Inst_Status.Pneu.Resource_Lock );

      return error;
}

/**begin_proto**/

UI_ERR DcSetInletCalPresZero ( pINLET_STATUS status )

/**end_proto**/
{

      if ( !EpcInlet(status) ) return NOT_ALLOWED;

      return ChangeInletCalPresZero( status );
}

/**begin_proto**/

UI_ERR ChangeInletCalPresZero ( pINLET_STATUS status )

/**end_proto**/
{

      pPRES_SENSOR_STRUCT sensor;
      U_INT16 temp;
      U_INT16 offset;
      UI_ERR error;

      temp = status->Tcomp_Tables->Thermistor.Module_Temperature;
      sensor = &status->Tcomp_Tables->Pres_Sensor;

      offset = CalcPresCalibOffset( status->Pres_Adc_Actual, sensor, temp );

      if ((error = ValidatePresOffset( offset, status->Dcm2_Per_IU, sensor, temp )) != OK ) return error;

      status->Calib.P_Sensor_Offset = offset;

      SendInletCalibRequest ( status );

      LogSetptChange( status->Position == FRNT_INLET ? F_INLET_CAL_PRES_OFFSET : B_INLET_CAL_PRES_OFFSET, 0, 0 );

      status->Ready.Setpt_Change = TRUE;
      return OK;
}

/**begin_proto**/

UI_ERR DcSetInletFactoryCalPresZero ( pINLET_STATUS status )

/**end_proto**/
{

      pPRES_SENSOR_STRUCT sensor;
      U_INT16 temp;
      U_INT16 offset;
      UI_ERR error;

      if ( !EpcInlet( status ) ) return NOT_ALLOWED;

      temp = status->Tcomp_Tables->Thermistor.Module_Temperature;
      sensor = &status->Tcomp_Tables->Pres_Sensor;

      offset = CalcPresCalibOffset( status->Pres_Adc_Actual, sensor, temp );

      if ((error = ValidatePresOffset( offset, status->Dcm2_Per_IU, sensor, temp )) != OK ) return error;

      status->Calib.P_Sensor_Offset = offset;
      status->Calib.P_Sensor_Gain   = CALIB_GAIN_SCALING;
      status->Calib.Calib_Pressure  = 0;
      status->Calib.F_Sensor_Offset = 0;
      status->Calib.F_Sensor_Gain   = CALIB_GAIN_SCALING;
      status->Calib.Calib_Flow      = 0;
      InitializeDateTime( &status->Calib.Calib_Date );

      SaveInletFactoryCalib ( status );

      LogSetptChange( status->Position == FRNT_INLET ? F_INLET_CAL_PRES_OFFSET : B_INLET_CAL_PRES_OFFSET, 0, 0 );

      status->Ready.Setpt_Change = TRUE;
      return OK;
}

/**begin_proto**/

UI_ERR ValidateInletCalPres ( pINLET_STATUS status, INT32 pres )

/**end_proto**/
{

      pPRES_SENSOR_STRUCT sensor;

      if ( !EpcInlet( status ) ) return NOT_ALLOWED;

      sensor = &status->Tcomp_Tables->Pres_Sensor;

      if ( status->Filtered_Current_Pressure == 0 ) return NOT_ALLOWED;
      if (!EnoughPresToCalibrate( status->Filtered_Current_Pressure,
                                  sensor,
                                  status->Dcm2_Per_IU )) return OUTSIDE_ALLOWED_RANGE;

      if ( pres <= 0 )                              return PARAM_TOO_SMALL;

      return OK;
}

/**begin_proto**/

UI_ERR SetInletCalPres ( pINLET_STATUS status, INT32 pres )

/**end_proto**/
{

      UI_ERR  error;
      U_INT16 pres_iu;

      pres_iu = ConvertPresDisplayToIu( pres, status->Dcm2_Per_IU );

      if (( error = ValidateInletCalPres( status, pres )) == OK )
      {
           LockResource( &Inst_Status.Pneu.Resource_Lock );

           error = ChangeInletCalPres ( status, pres, pres_iu );

           ReleaseResource( &Inst_Status.Pneu.Resource_Lock );
      }

      return error;
}

/**begin_proto**/

UI_ERR DcSetInletCalPres ( pINLET_STATUS status, INT32 pres_dcu )

/**end_proto**/
{

      UI_ERR  error;
      U_INT16 pres_iu;
      INT32   pres;

      if ( !EpcInlet( status ) ) return NOT_ALLOWED;

      pres_iu = ConvertPresDcuToIu    ( pres_dcu, status->Dcm2_Per_IU );
      pres    = ConvertPresIuToDisplay( pres_iu,  status->Dcm2_Per_IU );

      if (( error = ValidateInletCalPres( status, pres )) == OK )
      {
           error = ChangeInletCalPres ( status, pres, pres_iu );
      }

      return error;
}

/**begin_proto**/

UI_ERR ChangeInletCalPres ( pINLET_STATUS status, INT32 pres, U_INT16 pres_iu )

/**end_proto**/
{

      UI_ERR  error;
      U_INT16 gain;

      gain = CalcCalibGain ( status->Filtered_Current_Pressure, pres_iu, status->Calib.P_Sensor_Gain );

      if ( (error=ValidatePresCalibGain( gain )) != OK ) return error;

      status->Calib.P_Sensor_Gain  = gain;
      status->Calib.Calib_Pressure = pres_iu;

      SendInletCalibRequest ( status );

      LogSetptChange( status->Position == FRNT_INLET ? F_INLET_CAL_PRES : B_INLET_CAL_PRES, pres, (INT32)GetPresUnits());

      status->Ready.Setpt_Change = TRUE;
      return OK;
}

/**begin_proto**/

U_INT32 GetInletCalPres ( pINLET_STATUS status )

/**end_proto**/
{
      if ( !EpcInlet( status ) ) return 0;


      return ConvertPresIuToDisplay ( status->Calib.Calib_Pressure, status->Dcm2_Per_IU );

}

/**begin_proto**/

U_INT32 DcGetInletCalPres ( pINLET_STATUS status )

/**end_proto**/
{
      if ( !EpcInlet( status ) ) return 0;


      return ConvertPresIuToDcu ( status->Calib.Calib_Pressure, status->Dcm2_Per_IU );

}

/**begin_proto**/

INT32 GetMinPresRequiredToCalibrate ( pINLET_STATUS status )

/**end_proto**/
{

      return ConvertPresIuToDisplay ( GetPresRequiredToCalibrate( &status->Tcomp_Tables->Pres_Sensor ),
                                      status->Dcm2_Per_IU );

}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

INT32 DcGetInletCalFlowGain ( pINLET_STATUS status )

/**end_proto**/
{
      if ( !EpcInlet( status ) ) return 0;

    return SignedQuadWordMultiplyDivide( CALIB_GAIN_DC_SCALE,
                                         status->Calib.F_Sensor_Gain - CALIB_GAIN_SCALING,
                                         CALIB_GAIN_SCALING );
}

/**begin_proto**/

INT32 GetInletCalFlowZero ( pINLET_STATUS status )

/**end_proto**/
{
      pFLOW_SENSOR_STRUCT sensor;
      U_INT16 temp;

      if ( !EpcInlet( status ) ) return 0;

      sensor = &status->Tcomp_Tables->Flow_Sensor;
      temp = status->Tcomp_Tables->Thermistor.Module_Temperature;

      return  GetFlowOffsetDispUnits( status->Calib.F_Sensor_Offset, status->IU_Scaling, sensor, temp );
}

/**begin_proto**/

INT32 DcGetInletCalFlowZero ( pINLET_STATUS status )

/**end_proto**/
{
      pFLOW_SENSOR_STRUCT sensor;
      U_INT16 temp;

      if ( !EpcInlet( status ) ) return 0;

      sensor = &status->Tcomp_Tables->Flow_Sensor;
      temp = status->Tcomp_Tables->Thermistor.Module_Temperature;

      return  GetFlowOffsetDcUnits( status->Calib.F_Sensor_Offset, status->IU_Scaling, sensor, temp );
}

/**begin_proto**/

UI_ERR SetInletCalFlowZero ( pINLET_STATUS status )

/**end_proto**/
{
      if ( !EpcInlet(status) ) return NOT_ALLOWED;

      if (( status->Wkfile->On_Off == OFF ) || ( status->Shutdown )) return INVALID_OP;

      /* do not do resource locking here, it is done in the  */
      /* routine called by the change function               */

      BkgrndRequestFsZero( status, FALSE);

      return OK;
}

/**begin_proto**/

UI_ERR DcSetInletCalFlowZero ( pINLET_STATUS status )

/**end_proto**/
{
      switch ( status->Config->Type )
      {
          case SS:
          case PP:
          case ACI:
          case SIMDIST:
          case VOLATILES:
          case CIS3:
          case CIS4:
          case PTV:  if ( status->Config->Functional ) break;

                     /* intentional fall through */

          default:   return NOT_ALLOWED;
      }

      if (( status->Wkfile->On_Off == OFF ) || ( status->Shutdown )) return INVALID_OP;

      status->Flow_Sensor_Zero_State = (INT32)IN_PROGRESS;

      BkgrndRequestFsZero( status, TRUE);

      return OK;
}

/**begin_proto**/

UI_ERR DcGetInletCalFlowZeroState ( pINLET_STATUS status )

/**end_proto**/
{
      return (UI_ERR)status->Flow_Sensor_Zero_State;
}

/**begin_proto**/

U_INT32 GetInletCalFlow ( pINLET_STATUS status )

/**end_proto**/
{
    if ( !EpcInlet(status) ) return 0;

    return status->Calib.Calib_Flow;
}


/**begin_proto**/

U_INT32 DcGetInletCalFlow ( pINLET_STATUS status )

/**end_proto**/
{
    U_INT32 flow;

    if ( !EpcInlet(status) ) return 0;

    flow =  ConvertFlowDisplayToIu ( status->Calib.Calib_Flow, status->IU_Scaling );
    return  ConvertFlowIuToDcu     ( flow,                     status->IU_Scaling );
}


/**begin_proto**/

UI_ERR ValidateInletCalFlow ( pINLET_STATUS status, INT32 flow )

/**end_proto**/
{
      if ( !EpcInlet(status) ) return NOT_ALLOWED;

      if ( flow <= 0 ) return PARAM_TOO_SMALL;
      if ( flow > GetInletMaxFlow( status ) ) return PARAM_TOO_LARGE;

      if ( status->Filtered_Current_Total_Flow == 0 ) return NOT_ALLOWED;
      if (!EnoughFlowToCalibrate( status->Filtered_Current_Total_Flow,
                                  &status->Tcomp_Tables->Flow_Sensor,
                                  status->IU_Scaling )) return OUTSIDE_ALLOWED_RANGE;
      return OK;
}

/**begin_proto**/

UI_ERR SetInletCalFlow ( pINLET_STATUS status, INT32 flow )

/**end_proto**/
{

      UI_ERR  error;
      U_INT32 flow_iu;

      if ( !EpcInlet(status) ) return NOT_ALLOWED;

      flow_iu = ConvertFlowDisplayToIu( flow, status->IU_Scaling );

      if ((error = ValidateInletCalFlow( status, flow )) == OK )
      {
           LockResource( &Inst_Status.Pneu.Resource_Lock );

           error = ChangeInletCalFlow( status, flow, flow_iu );

           ReleaseResource( &Inst_Status.Pneu.Resource_Lock );
      }

      return error;
}

/**begin_proto**/

UI_ERR DcSetInletCalFlow ( pINLET_STATUS status, INT32 flow_dcu )

/**end_proto**/
{

      UI_ERR  error;
      U_INT32 flow_iu;
      INT32   flow;

      if ( !EpcInlet(status) ) return NOT_ALLOWED;

      flow_iu = ConvertFlowDcuToIu    ( flow_dcu, status->IU_Scaling );
      flow    = ConvertFlowIuToDisplay( flow_iu,  status->IU_Scaling );

      if ((error = ValidateInletCalFlow( status, flow )) == OK )
      {
           error = ChangeInletCalFlow( status, flow, flow_iu );
      }

      return error;
}


/**begin_proto**/

UI_ERR ChangeInletCalFlow ( pINLET_STATUS status, INT32 flow, U_INT32 flow_iu )

/**end_proto**/
{

      UI_ERR  error;
      U_INT16 gain;

      gain = CalcCalibGain ( status->Filtered_Current_Total_Flow, flow_iu, status->Calib.F_Sensor_Gain );

      if ( (error=ValidateFlowCalibGain( gain )) != OK ) return error;

      status->Calib.F_Sensor_Gain = gain;
      status->Calib.Calib_Flow = flow;
      SendInletCalibRequest ( status );

      LogSetptChange( status->Position == FRNT_INLET ? F_INLET_CAL_FLOW : B_INLET_CAL_FLOW, 0, 0 );

      status->Ready.Setpt_Change = TRUE;
      return OK;
}

/**begin_proto**/

INT32 GetMinFlowRequiredToCalibrate ( pINLET_STATUS status )

/**end_proto**/
{

      return ConvertFlowIuToDisplay ( GetFlowRequiredToCalibrate( &status->Tcomp_Tables->Flow_Sensor ),
                                      status->IU_Scaling );

}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

DATETIME GetInletCalibDate( pINLET_STATUS status )

/**end_proto**/
{

     return status->Calib.Calib_Date;

}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

UI_ERR DeleteInletCalib ( pINLET_STATUS status )

/**end_proto**/
{
   UI_ERR error;

   LockResource( &Inst_Status.Pneu.Resource_Lock );

   error = SendDeleteInletCalib ( status );

   ReleaseResource( &Inst_Status.Pneu.Resource_Lock );

   return error;

}

/**begin_proto**/

UI_ERR DcDeleteInletCalib ( pINLET_STATUS status )

/**end_proto**/
{
   UI_ERR error;

    error = SendDeleteInletCalib ( status );

   return error;

}

/**begin_proto**/

UI_ERR SendDeleteInletCalib ( pINLET_STATUS status )

/**end_proto**/
{
   if ( !EpcInlet( status ) ) return NOT_ALLOWED;
   if ( InletUserCalibState( status ) == FACTORY ) return INVALID_OP;

   SendInletScratchRequest ( status );

   LogSetptChange( status->Position == FRNT_INLET ? F_INLET_CAL_DELETED : B_INLET_CAL_DELETED, 0, 0 );

   status->Ready.Setpt_Change = TRUE;

   return OK;
}

/**begin_proto**/

UI_ERR TurnOffInletCalib( pINLET_STATUS status )

/**end_proto**/
{
    UI_ERR error;

    if ( (error =  ValidateInletCalibState( status, OFF )) == OK )
    {
        LockResource( &Inst_Status.Pneu.Resource_Lock );

        SendInletDisableUserRequest( status );

        ReleaseResource( &Inst_Status.Pneu.Resource_Lock );
    }

    return error;
}

/**begin_proto**/

UI_ERR DcTurnOffInletCalib( pINLET_STATUS status )

/**end_proto**/
{

    UI_ERR error;

    if ( (error =  ValidateInletCalibState( status, OFF )) == OK )
    {
        SendInletDisableUserRequest( status );
    }

    return error;
}


/**begin_proto**/

UI_ERR TurnOnInletCalib( pINLET_STATUS status )

/**end_proto**/
{
    UI_ERR error;

    if ( (error =  ValidateInletCalibState( status, ON )) == OK )
    {
        LockResource( &Inst_Status.Pneu.Resource_Lock );

        SendInletEnableUserRequest( status );

        ReleaseResource( &Inst_Status.Pneu.Resource_Lock );
    }

    return error;

}

/**begin_proto**/

UI_ERR DcTurnOnInletCalib( pINLET_STATUS status )

/**end_proto**/
{
    UI_ERR error;

    if ( (error =  ValidateInletCalibState( status, ON )) == OK )
    {
        SendInletEnableUserRequest( status );
    }

    return error;
}


/**begin_proto**/

UI_ERR ChangeInletCalibState( pINLET_STATUS status, ON_OFF  state )

/**end_proto**/
{
    UI_ERR error;

    if ( EpcInlet( status ) )
    {
        if (( state == OFF ) && ( InletUserCalibState( status ) == USER_ENABLED ))
        {
            DisableInletCalib( status );
            LogSetptChange( status->Position == FRNT_INLET ? F_INLET_CAL_DISABLED : B_INLET_CAL_DISABLED, 0, 0 );
            error = OK;
        }
        else if (( state == ON ) && ( InletUserCalibState( status ) == USER_DISABLED ))
        {
            EnableInletCalib( status );
            LogSetptChange( status->Position == FRNT_INLET ? F_INLET_CAL_ENABLED : B_INLET_CAL_ENABLED, 0, 0 );
            error = OK;
        }
        else
        {
            error = INVALID_OP;
        }
    }
    else
    {
        error = NOT_ALLOWED;
    }

    return error;

}

/**begin_proto**/

UI_ERR ValidateInletCalibState( pINLET_STATUS status, ON_OFF  state )

/**end_proto**/
{

/* there is a failure posible here, if multiple cmds to enable or */
/* disable calib are stacked in the gastask queue, this routine   */
/* can give false results.                                        */

    UI_ERR error;

    if ( EpcInlet( status ) )
    {
        if (( state == OFF ) && ( InletUserCalibState( status ) == USER_ENABLED ))
        {
            error = OK;
        }
        else if (( state == ON ) && ( InletUserCalibState( status ) == USER_DISABLED ))
        {
            error = OK;
        }
        else
        {
            error = INVALID_OP;
        }
    }
    else
    {
        error = NOT_ALLOWED;
    }

    return error;

}

/**begin_proto**/

CALIB_STATE InletUserCalibState( pINLET_STATUS status )

/**end_proto**/
{
     return status->Calib.Calib_State;
}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

BIT8 GetInletDiagMode( pINLET_STATUS status )

/**end_proto**/
{
    return status->Diag_Mode_Enabled;
}

/**begin_proto**/

BIT8 GetInletSolenoidValve( pINLET_STATUS status )

/**end_proto**/
{
    return status->Solenoid_Valve_Enable;
}


/**begin_proto**/

void SetInletDiagMode( pINLET_STATUS status, BIT8 mode )

/**end_proto**/
{
    status->Diag_Mode_Enabled = ( mode != 0 );
}

/**begin_proto**/

void SetInletSolenoidValve( pINLET_STATUS status, BIT8 mode )

/**end_proto**/
{
    status->Solenoid_Valve_Enable = ( mode != 0 );
}


/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

INT32 GetSprFlowConst( pINLET_STATUS status, GAS_TYPE gas )

/**end_proto**/
{
   U_INT32 flow_iu;
   INT32   dfdp_iu;

   if ( ! EpcInlet( status ) ) return 0;

   if ( ReadPurgeRegComp ( status, gas, &flow_iu, &dfdp_iu ) != OK )
   {
      TrashModule( status->Module_Number );
      return 0;
   }

   (void) dfdp_iu;

   return ConvertFlowIuToDcu ( flow_iu, status->IU_Scaling );

}

/**begin_proto**/

INT32 GetSprDflowConst( pINLET_STATUS status, GAS_TYPE gas )

/**end_proto**/
{
   U_INT32 flow_iu;
   INT32   dfdp_iu;

   if ( ! EpcInlet( status ) ) return 0;

   if ( ReadPurgeRegComp ( status, gas, &flow_iu, &dfdp_iu ) != OK )
   {
      TrashModule( status->Module_Number );
      return 0;
   }

   (void) flow_iu;

   dfdp_iu = SignedQuadWordMultiplyDivide( dfdp_iu * 1000,
                                           ConvertPresDcuToIu( 68948, status->Dcm2_Per_IU),
                                           DF_DP_SCALE * status->IU_Scaling );

   return dfdp_iu;

}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/***********************************************************************/
static void ResetReadyState( pHERE_I_COME ready )
{
    if (( ready->State == IGNORE_IF_NOT_READY ) ||
        ( ready->State == IGNORING_NOT_READY  ))
    {
         ready->State = NOT_IN_CONTROL_;
    }
}


/**begin_proto**/

void ResetPresReadinessStates( void )

/**end_proto**/
{

     ResetReadyState( &Inst_Status.Pneu.Frnt_Inlet.Ready.Pres );
     ResetReadyState( &Inst_Status.Pneu.Frnt_Inlet.Ready.Flow );

     ResetReadyState( &Inst_Status.Pneu.Back_Inlet.Ready.Pres );
     ResetReadyState( &Inst_Status.Pneu.Back_Inlet.Ready.Flow );

     ResetReadyState( &Inst_Status.Pneu.Frnt_Detector.Ready.Fuel_Pres );
     ResetReadyState( &Inst_Status.Pneu.Frnt_Detector.Ready.Util_Pres );
     ResetReadyState( &Inst_Status.Pneu.Frnt_Detector.Ready.Mug_Pres  );

     ResetReadyState( &Inst_Status.Pneu.Back_Detector.Ready.Fuel_Pres );
     ResetReadyState( &Inst_Status.Pneu.Back_Detector.Ready.Util_Pres );
     ResetReadyState( &Inst_Status.Pneu.Back_Detector.Ready.Mug_Pres  );

     ResetReadyState( &Inst_Status.Pneu.Frnt_Detector.Ready.Fuel_Flow );
     ResetReadyState( &Inst_Status.Pneu.Frnt_Detector.Ready.Util_Flow );
     ResetReadyState( &Inst_Status.Pneu.Frnt_Detector.Ready.Mug_Flow  );

     ResetReadyState( &Inst_Status.Pneu.Back_Detector.Ready.Fuel_Flow );
     ResetReadyState( &Inst_Status.Pneu.Back_Detector.Ready.Util_Flow );
     ResetReadyState( &Inst_Status.Pneu.Back_Detector.Ready.Mug_Flow  );

     ResetReadyState( &Inst_Status.Pneu.Aux.Aux_3.Ready.Pres );
     ResetReadyState( &Inst_Status.Pneu.Aux.Aux_4.Ready.Pres );
     ResetReadyState( &Inst_Status.Pneu.Aux.Aux_4.Ready.Pres );


}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/*     this routine is special to avoid deadlocks when powering        */
/*     on in recovery mode.  we could have a case where the flow       */
/*     system is in const pres mode, such that a now cool oven         */
/*     has caused a flow sensor to cap.  This should NOT keep          */
/*     the oven in hold off.  I know this is ugly, but there does      */
/*     not seem to be a better way.                                    */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

BIT8 OkToReleaseOvenHoldOff ( pINLET_STATUS status )

/**end_proto**/
{

   if ((( status->Config->Type == PP )          ||
        ( status->Config->Type == SS )          ||
        ( status->Config->Type == ACI)          ||
        ( status->Config->Type == SIMDIST)      ||
        ( status->Config->Type == PTV)          ||
        ( status->Config->Type == CIS4)         ||
        ( status->Config->Type == VOLATILES)    ||
        ( status->Config->Type == CIS3  )  ) &&
        ( status->Ready.Flow.Reported_Ready == FALSE ) &&
        ( status->Ready.Flow.Controlled ) &&
        ( status->Ready.Flow.In_Bounds  ) &&
        ( status->Ready.Flow.Capped     ))
   {
       return TRUE;
   }
   else
   {
       return FALSE;
   }

}


/***********************************************************************/
/* FUNCTION: Presence Functions                                        */
/* ========                                                            */
/*                                                                     */
/* PURPOSE: Determines if CPF label is present                         */
/*    presence is determined by a non-zero value in the first byte     */
/*    of the label.                                                    */
/*                                                                     */
/* RETURNED VALUE: TRUE or FALSE                                       */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

BIT8  GetCPFInletTitlePresence( POSITION position )

/**end_proto**/
{
   if (position==FRONT)
   {
      return ( FIName[0] != 0 ) ? TRUE : FALSE;
   }
   else
   {
      return ( BIName[0] != 0 ) ? TRUE : FALSE;
   }
}

/***********************************************************************/
/* FUNCTION: GetCPFInletTitle                                          */
/* ========                                                            */
/*                                                                     */
/* PURPOSE: Returns pointer to the title of the CPF Inlet              */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

BIT8  *GetCPFInletTitle( POSITION position )

/**end_proto**/
{
     return (position==FRONT) ? FIName : BIName;
}

/**begin_proto**/
#pragma SECTION UNDO
/**end_proto**/
